在JSON中禁用超文本应用程序语言(HAL)?

在JSON中禁用超文本应用程序语言(HAL)?,json,rest,spring-data,spring-data-jpa,spring-data-rest,Json,Rest,Spring Data,Spring Data Jpa,Spring Data Rest,在版本2.0.2.0中使用Spring数据REST和JPA 如何在JSON中禁用超文本应用程序语言HAL 我已经试过很多东西了,但都没有用。例如,我将Accept和Content-type头设置为application/json,而不是application/hal+json,但我仍然通过超链接接收json内容 例如,我想得到如下结果: { "name" : "Foo", "street" : "street Bar", "streetNumber" : 2, "streetLetter" :

在版本2.0.2.0中使用Spring数据REST和JPA

如何在JSON中禁用超文本应用程序语言HAL

我已经试过很多东西了,但都没有用。例如,我将Accept和Content-type头设置为application/json,而不是application/hal+json,但我仍然通过超链接接收json内容

例如,我想得到如下结果:

{
"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
     }
}
而不是:

{
"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"
     }
}
}
感谢您的帮助。

超媒体类型 Spring Data REST的默认设置使用HAL作为默认超媒体表示格式,因此服务器将为给定的Accept标头返回以下内容:

无标题->应用程序/hal+json->hal application/hal+json->application/hal+json->hal application/json->application/json->HAL这是默认配置 application/x-spring-data-verbose+json->application/x-spring-data-verbose+json->一种spring数据特定格式,使用链接容器的链接和内容作为集合项的包装。 如果您将RepositoryRestConfiguration.setDefaultMediaType…配置为非HAL格式,服务器将返回Spring数据特定的JSON格式,除非您明确要求使用application/HAL+JSON。诚然,配置选项可能有点误导,所以我提出了改进方案。该问题在2014年迪杰克斯特拉2.1 RC1中得到解决

请注意,我们实际上需要一种超媒体格式,以便能够表达托管资源之间的关系并实现服务器的可发现性。所以你不可能完全摆脱它。这主要是因为,如果您公开具有双向关系的实体或组成一个庞大的对象图,则很容易使服务器崩溃

内联相关实体 如果您永远不希望将扇区链接到它们并始终将其内联,那么一个选项就是首先将SectorRepository排除在作为REST资源导出的范围之外。可以通过使用@RepositoryRestResourceexported=false注释存储库接口来实现这一点

要获得在下一个示例中发布时返回的表示,请查看SpringDataREST2.1M1中引入的特性。它基本上允许您通过一个简单的界面在资源上创建与默认视图不同的可选视图

您基本上要定义一个接口:

@Projection(name = "foo", types = YourDomainClass.class)
interface Inlined {

  // list all other properties

  Sector getSector();
}
如果您将此接口放入域类的子包中,或者通过RepositoryRestConfiguration.ProjectOnConfiguration手动注册它,则公开域类的资源将接受请求参数投影,以便在本例中传入foo将呈现您想要的内联表示


提供了有关该功能的更多信息,定义了一个示例投影。

因此您需要两件事:

1清除链接字段 2包括相关行业领域

可能的解决方案对我有效:D

1摆脱_链接 为此,请创建以下类:

[... 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();
            }
        };
    }
}
我非常确定99%,但未经测试,您不需要这个类来删除下一点2所示的相关实体的_链接

2包括相关行业领域 对于这一点,您可以使用专门为该场景制作的。因为Spring示例非常有说服力,在这里复制它是很愚蠢的,我只想指出它:。 但为了记录和方便起见,我将粘贴spring示例的主要部分:

@Projection(name = "inlineAddress", types = { Person.class }) 
interface InlineAddress {
  String getFirstName();
  String getLastName();
  Address getAddress(); 
}
请参见,类型表示投影类型绑定到的类型。 摘录可以这样使用:

@RepositoryRestResource(excerptProjection = InlineAddress.class)
interface PersonRepository extends CrudRepository<Person, Long> {}
对你来说,扇区就是地址

最后说明

当返回数组时_links字段不会被删除,这样做太麻烦了;最后你会有这样的东西:

{
    "_embedded" : {
        "persons" : [ {person1}, {person2}, ..., {personN} ]
    },
    "_links" : {
        e.g. first, next, last, self, profile
    },
    "page" : {
      "size" : 1,
      "totalElements" : 10,
      "totalPages" : 10,
      "number" : 0
    }
}
正如你所看到的,即使我们删除了链接,这仍然是不够的;人们可能还希望_embedded被人取代,这将导致可维护性较差的代码和过多的spring侵入式覆盖。但是如果你真的想要这些,他应该开始检查RepositoryRestMvcConfiguration和RepositoryEntityController.getCollectionResource

Spring正在发展,因此我觉得有必要指出,这至少适用于:

spring-data-rest-webmvc 3.1.3.RELEASE
或者,如果您预选了spring引导版本:

spring-boot-starter-parent 2.1.1.RELEASE

这可能是由于反射API以不同的顺序返回方法造成的。但是,投影界面是开放的,可以通过Jackson注释进行自定义,因此@JsonPropertyOrder应该允许您根据需要自定义内容。我确认:@JsonPropertyOrder工作正常。非常感谢您的帮助。可以完全禁用hal吗?我只想检索带有实体ID的JSON。你不觉得这有点傻吗?如果我有100个模型,我需要创建100个投影。我不这么认为。我正在寻找一个配置标志,它允许我只发送Json或HalJson,而不是HalJsonT
SDR的超媒体特性的问题在于,简单的RESTAPI,即richardson成熟度模型的2级,是主流的,并经过生产验证。超媒体API 3级的可用性还没有定论。将SDR与超媒体捆绑在一起似乎使其处于实验状态,这使得它很难销售给任何需要生产准备API的人——或者我遗漏了什么?我喜欢你的答案,它为那些不了解摘录的人提供了一个很好的教程,它可能会帮助其他人。然而,根据Oliver Drotbohm(他是Spring数据项目负责人)的回答,这个问题可以追溯到2014年,我已经能够以一种更优雅的方式通过预测实现我试图实现的目标。我只是检查了我在代码中所做的工作:为了包含相关的扇形字段,我的主投影返回一个扇形投影,而不是扇形实体。这样我就根本没有链接了。如果您希望保留链接以供欣赏,您的答案是有效的:。在第1点中,我演示了如何删除_links字段;这确实不适用于阵列,但对于投影解决方案,我非常确定99%是相同的,对于嵌入式和page也是一样的。是的,最后非常相似。但我只能选择一个好答案,对不起。我相信你的回答会得到社区的赞赏。
spring-data-rest-webmvc 3.1.3.RELEASE
spring-boot-starter-parent 2.1.1.RELEASE