【问题标题】:How to exclude specific field from ObjectWriter如何从 ObjectWriter 中排除特定字段
【发布时间】:2021-02-02 10:05:20
【问题描述】:

这个想法是避免引入 DTO。用户提交不应有calculationSeed 的发布请求。该字段必须由服务设置并包含在响应中。 MapperFeature.USE_GETTERS_AS_SETTERS 不工作。我试图避免混乱的编程配置using filters。问题是 ow.writeValueAsString(john) 在 JUnit 测试中的 request 中包含该字段。

人物

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonPropertyOrder({"firstName", "lastName", "age", "calculationSeed"})
public class Person {
    @NotNull
    @JsonProperty("first_name")
    private String firstName;

    @NotNull
    @JsonProperty("last_name")
    private String lastName;

    private int age;

    @JsonIgnore
    private double calculationSeed;

    @JsonProperty
    public double getCalculationSeed() {
        return calculationSeed;
    }

    @JsonIgnore
    public void setCalculationSeed(double calculationSeed) {
        this.calculationSeed = calculationSeed;
    }
}

测试

@SpringJUnitConfig(DataCollectorE2EIT.Config.class)
public class e2EIT {

    @Configuration
    static class Config {}

    WebTestClient client;

    @BeforeEach
    void setUp(ApplicationContext context) {
        client = WebTestClient.bindToServer().baseUrl("http://localhost:8080").build();
    }

    static ObjectMapper mapper;
    static ObjectWriter ow;

    @BeforeAll
    public static void setUp() {
        mapper = new ObjectMapper().disable(MapperFeature.USE_GETTERS_AS_SETTERS);
        ow = mapper.writer().withDefaultPrettyPrinter();
    }

    @Test
    public void givenPersonData_whenPostRequest_then() throws Exception {
        Person john = Person.builder().firstName("John").lastName("Smith").age(25).build();

        client.post()
                .uri("/api/persons")
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(ow.writeValueAsString(john))
                .exchange()
                .expectStatus().isCreated()
                .expectBody(Person.class)
                .consumeWith(result -> {
                    assertThat(result.getResponseBody()).isNotNull();
                    assertEquals(0.09482345680132348, result.getResponseBody().getCalculationSeed());
                })
                .returnResult();
    }
}

日志

> POST http://localhost:8080/api/persons
> WebTestClient-Request-Id: [1]
> Content-Type: [application/json]
> Content-Length: [98]

{
  "first_name" : "John",
  "last_name" : "Smith",
  "age" : 25,
  "calculationSeed" : 0.0
}

< 201 CREATED Created
< Content-Type: [application/json]
< Transfer-Encoding: [chunked]
< Date: [Mon, 19 Oct 2020 15:26:01 GMT]

{"first_name":"John","last_name":"Smith","age":25,"calculation_seed":0.09482345680132348}

【问题讨论】:

    标签: java spring-boot junit jackson


    【解决方案1】:

    最简单的解决方案之一是将calculationSeed 更改为盒装类型Double。基元 double 不能默认为 null,这将被忽略,因此它将是 0.0

    但更普遍地,我面临的问题是人们倾向于将相同的 DTO 用于输入和输出,即使它们与您的情况似乎不同。

    在您的情况下,制作两个 DTO 也很容易,例如:

    // annotations...
    public class PersonDTO {
        // all but calculationSeed
    }
    

    // annotations...
    public class PersonDTOOut extends Person {
        private double calculationSeed;        
    }
    

    然后相应地使用这些。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-11
      • 1970-01-01
      • 1970-01-01
      • 2012-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多