当前位置: 首页 > 知识库问答 >
问题:

Lombok 1.18.0和Jackson 2.9.6不能一起工作

戚兴思
2023-03-14

更新后反序列化失败。

我将我的微服务从Spring1.5.10.RELEASE更新到Spring2.0.3.RELEASE,并将龙目岛1.16.14更新为1.18.0并将杰克逊数据类型-jsr3102.9.4更新为2.9.6

JSON字符串-

{"heading":"Validation failed","detail":"field must not be null"}

班级 -

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

   private final String heading;
   private final String detail;
   private String type;
}

方法调用-

ErrorDetail errorDetail = asObject(jsonString, ErrorDetail.class);

用于反序列化的方法 -

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);
    }
}

错误 -

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]

共有3个答案

景翰音
2023-03-14

您想要反序列化具有最终字段的类。因此,您需要声明一个包含要反序列化的最终字段的构造函数。

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

private final String heading;
private final String detail;
private String type;

@JsonCreator
public ErrorDetail(@JsonProperty("heading") String heading, @JsonProperty("detail") String detail) {
    this.heading = heading;
    this.detail = detail;
}
}

当使用mapper反序列化时,需要MapperFeature。ALLOW_FINAL_FIELDS_AS_MUTATORS将此属性设置为false。

private static <T> T asObject(final String str, Class<T> clazz) {
    try {
        return new ObjectMapper().configure(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS,false).readValue(str, clazz);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
祝英博
2023-03-14

编辑:这个答案现在有点过时了:有一个新的< code>@Jacksonized注释,来自https://project lombok . org/features/experimental/Jacksonized,它处理了这个答案中的许多样板文件。

让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 {
   }
}
邵飞宇
2023-03-14

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

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

更新:只有< code>@NoArgsConstructor和< code>@Getter(没有< code>@Setter)可能也可以工作(因为< code > INFER _ PROPERTY _ MUTATORS = true )。通过这种方式,您可以保持类的不可变,至少从常规(非反射)代码来看是如此。

解决方案 2:使用包含龙目岛线的龙目岛配置文件配置龙目岛以再次生成注释。(如果您使用的是模块,请确保 java.桌面位于模块路径上。在添加龙目岛.config 文件后进行清理并重新编译。

解决方案3:将Jackson的构建器支持与lombok的(< code > @ Jacksonized )< code > @ Builder /< code > @ super Builder

解决方案4:使用< code > javac (Java 8及更高版本)进行编译时,将< code>-parameters追加到命令中。这将在生成的类文件中存储构造函数和方法的参数名,因此可以通过反射检索它们。

 类似资料:
  • {“时间戳”:1553613278534,“状态”:400,“错误”:“错误请求”,“消息”:“必需的字符串参数'param2'不存在”,“路径”:“/MyURL/42”} 我希望PUT的工作就像POST一样,但它似乎不是。 不幸的是,我不能将参数作为QueryParam发送,因此我应该维护相同的请求调用,因为我正在重构一个完全以这种方式工作的现有endpoint。

  • 当异常发生在CompletableFuture中时,我试图设置一个默认值,我通过如下方法使其工作: 但是,当我试图在不好的事情发生时异常地使用complete来停止CompletableFuture,并按如下方式跟踪异常时,我无法像刚才那样捕捉到异常。 更新日期2018-06-09谢谢您的帮助,@Daniele 在join()之前封闭的句柄按预期工作。但在这种情况下,

  • 我正在试验把杰克逊和龙目岛结合起来。这些是我的课: 这些是我添加到类spth中的JAR: > 龙目岛:https://projectlombok.org/downloads/lombok.jar(1.16.10version) 此外,Netbeans项目被配置为“保存时不编译”、“生成调试信息”、“报告不推荐使用的API”、“跟踪java依赖项”、“Activacte注释处理”和“编辑器中的Act

  • 更改单元格值后,我的不会刷新。我可以双击一个单元格并更改它的值,但是当我按OK或者我点击离开单元格时,值会重置为上一个,这不是更新表。这是我的自定义表模型的代码,我不知道如何更新数据库,因为当我改变单元格的值时,表是从一个db中取出来的。 如果您需要其他东西,例如数据库或表编辑器的代码,请告诉我;)谢谢您的帮助:) --编辑--好的,我已经实现了setValueAt方法,但是当我单击单元格时,它给

  • pendingList 删除小部件实际上是将其从列表中删除。在用户取消任务后,该任务将从列表中“可视化地”删除,并调用方法,该方法调用。调用会导致FutureBuilder再次生成,但是在FutureBuilder再次生成时,调用尚未完成。因此,FutureBuilder将传递旧快照,这将导致ListView使用刚刚被取消的任务再次生成。这导致被解雇的列表者在被解雇后暂时出现,这看起来令人毛骨悚然

  • 根据它的Javadoc,将生成,其中的第一个值是subscribe和第一个next信号之间的经过时间。 以下测试不起作用 它将抛出异常: 我原以为经过的时间至少是1000ms,但结果只有11ms。