龙目岛1.18.0和杰克逊2.9.6没有合作

JHS*_*JHS 13 java jackson lombok spring-boot jackson-databind

更新后反序列化失败.

我从我的更新微服Spring 1.5.10.RELEASESpring 2.0.3.RELEASE,也更新了lombok1.16.141.18.0jackson-datatype-jsr3102.9.42.9.6.

JSON字符串 -

{"heading":"Validation failed","detail":"field must not be null"}
Run Code Online (Sandbox Code Playgroud)

班级 -

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class ErrorDetail {

   private final String heading;
   private final String detail;
   private String type;
}
Run Code Online (Sandbox Code Playgroud)

方法调用 -

ErrorDetail errorDetail = asObject(jsonString, ErrorDetail.class);
Run Code Online (Sandbox Code Playgroud)

用于反序列化的方法 -

import com.fasterxml.jackson.databind.ObjectMapper;
// more imports and class defination.

private static <T> T asObject(final String str, Class<T> clazz) {
    try {
        return new ObjectMapper().readValue(str, clazz);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

错误 -

java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.foo.bar.ErrorDetail` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (String)"{"heading":"Validation failed","detail":"field must not be null"}"; line: 1, column: 2]
Run Code Online (Sandbox Code Playgroud)

Jan*_*eke 29

Lombok停止生成@ConstructorProperties版本为1.16.20的构造函数(请参阅changelog),因为它可能会破坏使用模块的Java 9+应用程序.该注释包含构造函数参数的名称(它们在编译类时被删除,因此这是一种解决方法,以便仍可以在运行时检索参数名称).由于默认情况下不会生成注释,因此Jackson无法将字段名称映射到构造函数参数.

解决方案1: 使用@NoArgsConstructor@Setter,但你将失去不变性(如果这对你很重要).

更新: Just @NoArgsConstructor@Getter(without @Setter)也可以工作(因为INFER_PROPERTY_MUTATORS=true).通过这种方式,您可以保持类不可变,至少从常规(非反射)代码.

解决方案2:使用lombok.config包含该行文件 配置lombok以再次生成注释lombok.anyConstructor.addConstructorProperties = true.(如果您使用的是模块,请确保java.desktop在模块路径上.)

解决方案3: 使用杰克逊的制造商的支持,结合龙目岛的@Builder,如所描述这里.

  • 谢谢你。第一个选项成功了。不过第二个没用。 (3认同)
  • 广告2)您是否将`lombok.config`添加到项目的根文件夹中?另外请注意,这样做之后必须清理并重新编译。 (2认同)

Ran*_*kar 6

使jackson和lombok相互配合的最佳方法是始终使DTO不可变,并告诉jackson使用生成器将其反序列化为对象。

不可变对象是一个好主意,原因很简单,当无法在现场修改字段时,编译器可以进行更积极的优化。

为此,您需要两个注释:JsonDeserialize和JsonPojoBuilder。

例:

@Builder
@Value // instead of @Data
@RequiredArgsConstructor
@NonNull // Best practice, see below.
@JsonDeserialize(builder = ErrorDetail.ErrorDetailBuilder.class)
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class ErrorDetail {

   private final String heading;

   // Set defaults if fields can be missing, like this:
   @Builder.Default
   private final String detail = "default detail";

   // Example of how to do optional fields, you will need to configure
   // your object mapper to support that and include the JDK 8 module in your dependencies..
   @Builder.Default
   private Optional<String> type = Optional.empty()

   @JsonPOJOBuilder(withPrefix = "")
   public static final class ErrorDetailBuilder {
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 噗,这是一个打算删除样板文件的库的大量样板注释。 (18认同)
  • 实际上,所有这些内容都已合并到一个注释中:`@Jacksonized` https://projectlombok.org/features/experimental/Jacksonized (5认同)