是否可以在类级别为不同的数据类型配置 Jackson 自定义反序列化器?

2023-12-14

我需要反序列化一个又长又复杂的json,我为此编写了一组java类来映射数据,并且我必须为许多不同类型的字段编写自定义反序列化器(包括String、Boolean、BigDecimal等).

我知道我可以使用相应的自定义反序列化器注释 java 类中的所有字段(如下所示),但随后我需要注释所有类中的几乎所有字段。

@JsonDeserialize(using = CustomBooleanJsonDeserializer.class)
private boolean active;

我还知道我可以在Spring默认中注册一个模块ObjectMapper (like here),但我只想将这些自定义反序列化器用于这些特定的类。

@Bean
public Module customDeserializersModule() {
    SimpleModule module = new SimpleModule();
    module.addDeserializer(Boolean.class, new CustomBooleanJsonDeserializer());
    // add other custom deserializers 
    return module;
}

我什至知道我可以使用自定义ObjectMapper in the RestController,但我不想放弃通过自动数据绑定的便利@RequestBody,因为我必须防止其他人在没有必要的自定义反序列化器的情况下使用它。

@RequestMapping(method = RequestMethod.POST, value = "/data")
public ResponseEntity<ServerInfo> register(@RequestBody DataMapper data) {
   // DataMapper is the target POJO class of the json's deserialization
}

简而言之,我正在班级层面寻找类似的东西:

@JsonDeserialize(using = CustomStringJsonDeserializer.class, forType = String.class)
@JsonDeserialize(using = CustomBooleanJsonDeserializer.class, forType = Boolean.class)
@JsonDeserialize(using = CustomBigDecimalJsonDeserializer.class, forType = BigDecimal.class)
public class DataMapper implements Serializable {
    // obviously, @JsonDeserialize doesn't have a forType method
}

或者也许有某种方式实现自定义解串器为了DataMapper类,定义如何根据其数据类型反序列化每个字段(无需注释每个字段):

@JsonDeserialize(using = DataMapperJsonDeserializer.class)
public class DataMapper implements Serializable {
    // How can I implement the DataMapperJsonDeserializer with these 
    // characteristics? I know about the ContextualDeserializer interface, 
    // but I don't know how to use it without annotating each field.
}

或某种方式将模块的效果限制为一个包或一组类:

module.restrictedTo(/*some package or set of classes*/);
// com.fasterxml.jackson.databind.Module doesn't have a restrictedTo method

您可以为该类定义自定义反序列化器(作为问题中的第二个想法)并使用您自己的自定义ObjectMapper inside:

public class DataMapperJsonDeserializer extends JsonDeserializer<DataMapper> {

    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy");

    static {
        SimpleModule module = new SimpleModule();
        module.addDeserializer(BigInteger.class, new CustomBigIntegerJsonDeserializer());
        module.addDeserializer(BigDecimal.class, new CustomBigDecimalJsonDeserializer());
        module.addDeserializer(Boolean.class, new CustomBooleanJsonDeserializer());
        module.addDeserializer(String.class, new CustomStringJsonDeserializer());
        objectMapper.registerModule(module);
        objectMapper.addMixIn(DataMapper.class, DefaultJsonDeserializer.class);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.setDateFormat(simpleDateFormat);
    }

    @Override
    public DataMapper deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        return objectMapper.readValue(jsonParser, DataMapper.class);
    }

    @JsonDeserialize
    private interface DefaultJsonDeserializer {
        // Reset default json deserializer
    }

}

注意使用Jackson 混合注释 (the DefaultJsonDeserializer 界面)从动态删除自定义解串器POJO类,避免StackOverflowError否则会由于以下原因而被抛出objectMapper.readValue(jsonParser, DataMapper.class).


然后,只需注释POJO class:

@JsonDeserialize(using = DataMapperJsonDeserializer.class)
public class DataMapper implements Serializable {
    // It is not necessary to annotate each field with custom deserializers.
}

您甚至可以添加其他POJO类作为领域DataMapper并且每种类型的自定义反序列化器将自动应用于其字段,而不需要注释。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以在类级别为不同的数据类型配置 Jackson 自定义反序列化器? 的相关文章

随机推荐