可以使用自定义 Jackson JsonDeserializer 反序列化非嵌套值吗?

Can a non-nested value be deserialized using a custom Jackson JsonDeserializer?

我正在处理一个项目,该项目使用自定义 Jackson JsonDeserializer 来反序列化一个对象,该对象的字段包含来自 JSON 的无法直接反序列化的第三方类型。通过使用 @JsonDeserialize(using = CustomTypeDeserializer.class).

注释字段来使用此反序列化器
public static class OuterType {
    @JsonDeserialize(using = CustomTypeDeserializer.class)
    private CustomType customType;

    public CustomType getCustomType() { return customType; }
    public void setCustomType(CustomType customType) { this.customType = customType; }
}

当要反序列化的类型是另一种类型的 属性 时,这很好用,因为有地方可以放置 @JsonDeserialize 注释。它不起作用的一件事是直接反序列化类型。

new ObjectMapper().readValue(json, CustomType.class); // Doesn't work.

我似乎不能直接使用反序列化器,因为它的编写方式似乎无法直接反序列化 ObjectMapper.[=17 上下文之外的值=]

请注意,要反序列化的类型是第三方类型,因此我无法使用 Jackson 注释对其进行修改。

有没有办法使用自定义反序列化器反序列化非嵌套类型?

一种方法是编写包含反序列化器的自定义 Module 模块,并将模块添加到 ObjectMapper.

public static class CustomTypeModule extends SimpleModule {
    public CustomTypeModule() {
        addDeserializer(CustomType.class, new CustomTypeDeserializer());
    }
}
JsonMapper objectMapper = JsonMapper.builder().addModule(new CustomTypeModule()).build();
CustomType value = objectMapper.readValue(json, CustomType.class);

如果您不想修改您的全局应用程序 ObjectMapper(使该模块可用于所有请求),您可以将其应用到仅用于此操作的 ObjectMapper 的副本.

JsonMapper objectMapper = JsonMapper.builder().build();

// ...

JsonMapper customTypeMapper = objectMapper.rebuild().addModule(new CustomTypeModule()).build();
// OR
ObjectMapper customTypeMapper = objectMapper.copy().registerModule(new CustomTypeModule())

CustomType value = customTypeMapper.readValue(json, CustomType.class);

如果您的可能情况保证自定义反序列化器将始终应用于您的类型而不考虑它是否嵌套,您可以直接在您的 CustomType [=23] 上应用 JsonDeserialize 注释=] 作为解决方案的替代方案:

@JsonDeserialize(using = CustomTypeDeserializer.class)
public class CustomType {}

如果您想在 json 中提取 CustomType 对象,您可以使用 readTree and treeToValue 方法:

//customType object labelled with "customType"
JsonNode tree = mapper.readTree(src).get("customType");
CustomType custom = mapper.treeToValue(tree, CustomType.class);

如果这不是第三方类型,则可以使用 @JsonDeserialize 注释对类型本身进行注释。由于类型是外部控制的,不能修改,所以不能直接使用这种方式。

然而,Jackson mixin 可用于配置 ObjectMapper(或其副本)以将类型视为存在 @JsonDeserialize 注释:

@JsonDeserialize(using = CustomTypeDeserializer.class)
public abstract class CustomTypeMixin {}
JsonMapper objectMapper = JsonMapper.builder()
        .addMixIn(CustomType.class, CustomTypeMixin.class).build();
CustomType value = objectMapper.readValue(json, CustomType.class));