@Jacksonized @Builder @Value 产生空 json

@Jacksonized @Builder @Value produce empty json

版本:

龙目岛:1.18.20 spring-引导:2.5.4

lombok.config(使用 IntelliJ 生成的默认值)

# add @lombok.Generated annotation to all Lombok generated methods
config.stopBubbling = true
lombok.addLombokGeneratedAnnotation = true

POJO

Payload.java

@Jacksonized @Builder @Value
public class Payload<T> {
    @Getter(AccessLevel.NONE)
    private T content;

    /**
     * @return payload content
     */
    public T get() {
        return content;
    }
}

ApiRequest.java

@Jacksonized @Builder @Value
public class ApiRequest<T> {
    private Date timestamp;
    private Payload<T> payload;
}

Metadata.java

@Jacksonized @Builder(toBuilder = true) @Value
public class Metadata {
    private String element;
    private String threshold;
    private String groupType;
    private String groupId;
    private String groupName;
    private String groupPath;
    private Instant from;
    private Instant to;

}

MyRestController.java

@Slf4j
@Validated
@RestController
@RequestMapping(value = "/test", produces = MediaType.APPLICATION_JSON_VALUE)
@RequestScope
public class MyRestController {
    @RequestMapping(
            path = "/process",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public ApiResponse process(@RequestBody ApiRequest<List<Metadata>> apiRequest) {
        log.info("Received request: " + apiRequest);
        return null; // Ignore for now
    }

    /*public ApiResponse process(@RequestBody String json) {
        log.info("Received request: " + json);
        return null; // Ignore for now
    }*/
}

TestClass.class

public class TestClass {

    public static void main(String[] args) throws Exception {
        String fromStr = "2021-09-05T00:00:00Z";
        String toStr = "2021-09-11T23:59:59Z";
        Instant from = Instant.parse(fromStr);
        Instant to = Instant.parse(toStr);
        String groupName = "SomeGroupName";
        String groupPath = "SomeGroupPath";

        List<Metadata> metadataList = new ArrayList<>();
        metadataList.add(Metadata.builder().element("e1").threshold("48").groupName(groupName).groupPath(groupPath).from(from).to(to).build());
        metadataList.add(Metadata.builder().element("e2").threshold("35").groupName(groupName).groupPath(groupPath).from(from).to(to).build());
        metadataList.add(Metadata.builder().element("e3").threshold("90").groupName(groupName).groupPath(groupPath).from(from).to(to).build());

        Payload<List<Metadata>> payload = Payload.<List<Metadata>>builder().content(metadataList).build();
        ApiRequest<List<Metadata>> apiRequest = ApiRequest.<List<Metadata>>builder().payload(payload).build();

        RestTemplate rt = new RestTemplate();
        final String baseUrl = "http://localhost:8080/test/process";
        URI uri = new URI(baseUrl);
        ResponseEntity<ApiResponse> response = rt.postForEntity(uri, apiRequest, ApiResponse.class);
        ApiResponse r = response.getBody();
    }
}

当我运行这个设置时,MyRestController收到一个空值apiRequest。如果我取消注释控制器中注释掉的方法,则字符串化的 json 也为空。我在 Internet 上看到人们声称他们已经能够使用 @Jacksonized 序列化和反序列化不可变 POJO 的示例。

  1. 我做错了什么导致序列化失败吗?
  2. 假设序列化有效,那么我是否需要对 ApiResponse 进行一些特殊处理才能反序列化?

运行运行程序时的当前结果:

Received request: {"timestamp":null,"payload":{}}

注:

我已经看过这个讨论 。但我更倾向于@Jacksonized工作。

更新 - 已解决

问题出在 Payload.java POJO 上。如下修改 POJO 解决了问题:

@Jacksonized @Builder @Value
public class Payload<T> {
    @Getter(AccessLevel.NONE)
    private T content;

    /**
     * @return payload content
     */
    @JsonProperty("content") // ADDED THIS TO TELL JACKSON TO USE THIS GETTER FOR content
    public T get() {
        return content;
    }
}

正如@Jan Rike 所建议的,我将添加我的解决方案作为答案。

问题出在 Payload.java POJO 上。如下修改 POJO 解决了问题:

@Jacksonized @Builder @Value
public class Payload<T> {
    @Getter(AccessLevel.NONE)
    private T content;

    /**
     * @return payload content
     */
    @JsonProperty("content") // ADDED THIS TO TELL JACKSON TO USE THIS GETTER FOR content
    public T get() {
        return content;
    }
}

没有这个,Jackson 一直在寻找 getContent() 方法但失败了,因为它不存在(由于 @Getter(AccessLevel.NONE)