在 JSON 中禁用超文本应用程序语言 (HAL)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23264044/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Disable Hypertext Application Language (HAL) in JSON?
提问by jplandrain
Using Spring Data REST with JPA in version 2.0.2.RELEASE.
在 2.0.2.RELEASE 版本中使用带有 JPA 的 Spring Data REST。
How can I disable Hypertext Application Language (HAL) in the JSON ? http://stateless.co/hal_specification.html
如何在 JSON 中禁用超文本应用程序语言 (HAL)?http://stateless.co/hal_specification.html
I have tried many things already, but to no avail. For example, I have set Accept and Content-type headers to "application/json" instead of "application/hal+json" but I still receive the JSON content with hyper links.
我已经尝试了很多东西,但都无济于事。例如,我已将 Accept 和 Content-type 标头设置为“application/json”而不是“application/hal+json”,但我仍然收到带有超链接的 JSON 内容。
For example, I'd like to get something like:
例如,我想得到类似的东西:
{
"name" : "Foo",
"street" : "street Bar",
"streetNumber" : 2,
"streetLetter" : "b",
"postCode" : "D-1253",
"town" : "Munchen",
"country" : "Germany",
"phone" : "+34 4410122000",
"vat" : "000000001",
"employees" : 225,
"sector" : {
"description" : "Marketing",
"average profit": 545656665,
"average employees": 75,
"average profit per employee": 4556
}
}
Instead of:
代替:
{
"name" : "Foo",
"street" : "street Bar",
"streetNumber" : 2,
"streetLetter" : "b",
"postCode" : "D-1253",
"town" : "Munchen",
"country" : "Germany",
"phone" : "+34 4410122000",
"vat" : "000000001",
"employees" : 225,
"_links" : {
"self" : {
"href" : "http://localhost:8080/app/companies/1"
},
"sector" : {
"href" : "http://localhost:8080/app/companies/1/sector"
}
}
}
Thanks for your help.
谢谢你的帮助。
采纳答案by Oliver Drotbohm
(Hyper)media types
(超)媒体类型
The default settings for Spring Data REST use HAL as the default hypermedia representation format, so the server will return the following for the given Acceptheaders:
Spring Data REST 的默认设置使用 HAL 作为默认的超媒体表示格式,因此服务器将为给定的Accept标头返回以下内容:
- No header ->
application/hal+json-> HAL application/hal+json->application/hal+json-> HALapplication/json->application/json-> HAL (this is what the default configures)application/x-spring-data-verbose+json->application/x-spring-data-verbose+json-> a Spring Data specific format (usinglinksfor the links container andcontentas wrapper for the collection items.
- 没有标题 ->
application/hal+json-> HAL application/hal+json->application/hal+json-> 哈尔application/json->application/json-> HAL(这是默认配置的)application/x-spring-data-verbose+json->application/x-spring-data-verbose+json-> 特定于 Spring Data 的格式(links用于链接容器和content集合项的包装器。
If you configure RepositoryRestConfiguration.setDefaultMediaType(…)to a non-HAL format, the server will return the Spring Data specific JSON format unless you explicitly ask for application/hal+json. Admittedly the configuration option is probably a bit misleading, so I filed DATAREST-294to improve this. The issue was resolved in 2.1 RC1 (Dijkstra) 2014.
如果您配置RepositoryRestConfiguration.setDefaultMediaType(…)为非 HAL 格式,服务器将返回 Spring Data 特定的 JSON 格式,除非您明确要求application/hal+json. 诚然,配置选项可能有点误导,所以我提交了DATAREST-294来改进这一点。该问题已在 2.1 RC1 (Dijkstra) 2014 中解决。
Note that we effectively need a hypermedia format in place to be able to express relations between managed resources and enable discoverability of the server. So there's no way you'll be able to get rid of it completely. This is mostly due to the fact that you could easily crash the server if you expose entities that have bidirectional relationships or make up an enormous object graph.
请注意,我们实际上需要一种超媒体格式,以便能够表达托管资源之间的关系并启用服务器的可发现性。所以你不可能完全摆脱它。这主要是因为如果公开具有双向关系的实体或构成巨大的对象图,则很容易使服务器崩溃。
Inlining related entities
内联相关实体
If you never want to have sectors linked to and always inline them, one option is to simply exclude the SectorRepositoryfrom being exported as a REST resource in the first place. You can achieve this by annotating the repository interface with @RepositoryRestResource(exported = false).
如果您永远不想将扇区链接到并始终内联它们,那么一个选择是首先简单地排除将SectorRepository其作为 REST 资源导出。您可以通过使用@RepositoryRestResource(exported = false).
To get a representation returned as you posted in your lower example have a look at the projectionsfeature introduced in Spring Data REST 2.1 M1. It basically allow you to craft optional views on a resource that can differ from the default one via a simple interface.
要获得在下例中发布的表示返回,请查看Spring Data REST 2.1 M1 中引入的投影功能。它基本上允许您通过简单的界面在资源上制作可选视图,这些视图可能与默认视图不同。
You'd basically define an interface:
你基本上定义了一个接口:
@Projection(name = "foo", types = YourDomainClass.class)
interface Inlined {
// list all other properties
Sector getSector();
}
If you either put this interface into a (sub)package of your domain class or manually register it via RepositoryRestConfiguration.projectionConfiguration()the resources exposing YourDomainClasswill accept a request parameter projectionso that passing in fooin this example would render the inlined representation as you want it.
如果您将此接口放入域类的(子)包中或通过RepositoryRestConfiguration.projectionConfiguration()资源公开手动注册它,YourDomainClass则将接受请求参数,projection以便foo在此示例中传入将按照您的需要呈现内联表示。
This commithas more info on the feature in general, this commithas an example projection defined.
回答by adrhc
So you want 2 things:
所以你想要两件事:
1) get rid of _linksfield
2) include the related sectorfield
1) 去掉_links字段
2) 包含相关sector字段
Possible solution(works for me :D)
可能的解决方案(对我有用:D)
1) get rid of _links
For this create the class below:
1)摆脱_links
为此创建下面的类:
[... package declaration, imports ...]
public class MyRepositoryRestMvcConfiguration extends RepositoryRestMvcConfiguration {
public MyRepositoryRestMvcConfiguration(ApplicationContext context, ObjectFactory<ConversionService> conversionService) {
super(context, conversionService);
}
@Bean
protected LinkCollector linkCollector() {
return new LinkCollector(persistentEntities(), selfLinkProvider(), associationLinks()) {
public Links getLinksFor(Object object, List<Link> existingLinks) {
return new Links();
}
};
}
}
and use it e.g.:
并使用它,例如:
[... package declaration, imports ...]
@SpringBootApplication
@Import({MyRepositoryRestMvcConfiguration.class})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
I'm pretty sure (99%, but not tested) that you won't need this class for removing the _linksfor the related entity/entities includedthe way next point (2) is showing.
我很确定(99%,但没有经过测试)您不需要这个类来删除_links相关实体/实体包括下一点 (2) 显示的方式。
2) include the related sectorfield
For this you could use Excerpts(especially made for this scenario). Because the Spring example is so eloquent and it's silly to just copy it here I'll just point it: https://docs.spring.io/spring-data/rest/docs/3.1.x/reference/html/#projections-excerpts.excerpting-commonly-accessed-data.
But just for the record and your convenience I'll paste the main parts of the spring example:
2)包括相关sector字段
为此,您可以使用摘录(特别是为此场景制作)。因为 Spring 的例子太有说服力了,只是在这里复制它很愚蠢,我只是指出它:https: //docs.spring.io/spring-data/rest/docs/3.1.x/reference/html/#projections -excerpts.excerpting-commonly-accessed-data。
但只是为了记录和您的方便,我将粘贴弹簧示例的主要部分:
@Projection(name = "inlineAddress", types = { Person.class })
interface InlineAddress {
String getFirstName();
String getLastName();
Address getAddress();
}
see at Projection javadocthat typesmeans The type the projection type is bound to.
The excerptcould be used this way:
请参阅Projection javadoc,这types意味着投影类型绑定到的类型。
该摘录可以这样使用:
@RepositoryRestResource(excerptProjection = InlineAddress.class)
interface PersonRepository extends CrudRepository<Person, Long> {}
in order to get this (when also using MyRepositoryRestMvcConfiguration):
为了得到这个(当还使用MyRepositoryRestMvcConfiguration 时):
{
"firstName" : "Frodo",
"lastName" : "Baggins",
"address" : {
"street": "Bag End",
"state": "The Shire",
"country": "Middle Earth"
}
}
For you the sectoris the equivalent of address.
对你sector来说,相当于address.
Final notes
最后的笔记
When returning arrays the _linksfield won't be removed (it's too intrusive to do it); in the end you'll have something like this:
返回数组时,该_links字段不会被删除(这样做太麻烦了);最后你会得到这样的东西:
{
"_embedded" : {
"persons" : [ {person1}, {person2}, ..., {personN} ]
},
"_links" : {
e.g. first, next, last, self, profile
},
"page" : {
"size" : 1,
"totalElements" : 10,
"totalPages" : 10,
"number" : 0
}
}
As you can see even if we'd have _linksremoved that still won't be enough; one would probably also want _embeddedreplaced by personswhich would lead to less maintainable code (too much spring intrusive overrides). But if one really wants these too he should start checking RepositoryRestMvcConfigurationand RepositoryEntityController.getCollectionResource.
正如你所看到的,即使我们已经_links删除了这仍然是不够的;一个人可能还希望_embedded由personswhich替换,这会导致代码的可维护性降低(太多的 spring 侵入性覆盖)。但如果一个人也真的想要这些,他应该开始检查RepositoryRestMvcConfiguration和RepositoryEntityController.getCollectionResource。
Spring is evolving so I feel the need to point that this works with at least:
Spring 正在发展,所以我觉得有必要指出这至少适用于:
spring-data-rest-webmvc 3.1.3.RELEASE
or, if you prefeer spring boot version:
或者,如果您更喜欢 Spring Boot 版本:
spring-boot-starter-parent 2.1.1.RELEASE

