【问题标题】:RepositoryRestMvcConfiguration's ObjectMapper vs. Spring Boot default ObjectMapper?RepositoryRestMvcConfiguration 的 ObjectMapper 与 Spring Boot 默认的 ObjectMapper?
【发布时间】:2017-05-01 11:14:07
【问题描述】:

我正在使用 RepositoryRestMvcConfiguration 来微调其余存储库的行为:

@Configuration
public class WebConfig extends RepositoryRestMvcConfiguration {
    @Override
    protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
      config.setReturnBodyOnCreate(true);
}

缺点是扩展类引入了它自己的 ObjectMapper bean,导致here 中描述的冲突。推荐的解决方法是使用扩展类将 ObjectMapper bean 标记为 @Primary,但是来自 RepositoryRestMvcConfiguration 的 bean 在序列化嵌套实体时具有不同的行为。

让我们假设以下实体:

@Entity class Parent {
    @Id Long id;
    @OneToMany @JsonManagedReference List<Child> children;
    // usual getters and setters for fields...
}

@Entity class Child {
    @Id Long id;
    @ManyToOne @JsonBackReference Parent parent;
    @ManyToOne @JsonBackReference School school;
    public getSchooldId() { return school.getId(); }
    // usual getters and setters for fields...
}

@Entity class School {
    @Id Long id;
    @OneToMany @JsonManagedReference List<Child> children;
    // usual getters and setters for fields...
} 

使用默认的 Spring Boot ObjectMapper 会得到预期的结果(渲染嵌套实体):

{"id": 1, "children":[{"id":2, "schoolId":7},{"id":3, "schooldId":8}]}

但是来自RepositoryRestMvcConfiguration 的 ObjectMapper 忽略了子实体:

{"id": 1}

配置RepositoryRestMvcConfiguration ObjectMapper 以实现与 Spring Boot 默认相同的行为的正确方法是什么?

【问题讨论】:

    标签: java spring-boot jackson spring-data spring-data-rest


    【解决方案1】:

    RepositoryRestMvcConfiguration 创建两个 objectMapper 对象。

    1. objectMapper 供内部框架使用。
    2. halObjectMapper 负责渲染集合Resources 和Links。

    您可以尝试通过使用限定符自动装配 objectMapper 来实现所需的结果:

    @Qualifier('_halObjectMapper')
    

    编辑:用于渲染关联/嵌套属性

    默认情况下,Spring data-rest 不会呈现关联(reference),因为它们在 HATEOAS 规范下可用(您的 json 的 _link 部分)。 如果您想呈现关联,您只需要使用 Projections

    这个Person有几个属性:id是主键,firstName和lastName是数据属性,address是指向另一个域对象的链接

    @Entity
    public class Person {
    
      @Id @GeneratedValue
      private Long id;
      private String firstName, lastName;
    
      @OneToOne
      private Address address;
      …
    }
    

    将被渲染:

       {
      "firstName" : "Frodo",
      "lastName" : "Baggins",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/persons/1"
        },
        "address" : {
          "href" : "http://localhost:8080/persons/1/address"
        }
        }
        }
    

    默认情况下,Spring Data REST 将导出这个域对象,包括它的所有属性。 firstName 和 lastName 将作为它们的纯数据对象导出。关于地址属性有两个选项。一种选择是也为地址定义一个存储库。

    还有另一条路线。如果 Address 域对象没有自己的存储库定义,Spring Data REST 将直接在 Person 资源中内联数据字段。

    【讨论】:

    • 不幸的是,这没有帮助。 1) objectMapper 也是 @Autowired 其他 Spring Boot 代码(例如,org.springframework.boot.actuate.autoconfigure.EndpointMBeanExportAutoConfiguration 中的构造函数) 2) halObjectMapper 可以使用 @Override @Bean @Primary public ObjectMapper objectMapper() { return super.halObjectMapper(); } 设置为默认值,但结果与其他 objectMapper - 嵌套实体不呈现为 JSON
    • 好的,现在我明白你的问题了。
    • 这对于 Spring Data Rest 存储库端点是正确的,但不适用于 ObjectMapper 的独立使用(例如,在控制器中自动装配)。默认的 ObjectMapper(在 RepositoryRestMvcConfiguration 未扩展时可通过自动装配获得)即使没有投影也会按预期呈现嵌套实体。一旦我出于配置目的扩展RepositoryRestMvcConfiguration,objectMapper/halObjectMapper 在独立模式下使用时不再呈现嵌套实体。
    • 我修复了限定符,它以_开头
    猜你喜欢
    • 2018-03-31
    • 1970-01-01
    • 2020-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2019-07-27
    相关资源
    最近更新 更多