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

Nic*_*lau 4 java spring json jackson deserialization

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

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

@JsonDeserialize(using = CustomBooleanJsonDeserializer.class)
private boolean active;
Run Code Online (Sandbox Code Playgroud)

我还知道我可以在 Spring 默认情况下注册一个模块ObjectMapper(如此),但我只想对这些特定的类使用这些自定义反序列化器。

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

ObjectMapper我什至知道我可以在 中使用自定义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
}
Run Code Online (Sandbox Code Playgroud)

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

@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
}
Run Code Online (Sandbox Code Playgroud)

或者也许有某种方法为类实现自定义反序列化器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.
}
Run Code Online (Sandbox Code Playgroud)

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

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

Nic*_*lau 7

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

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
    }

}
Run Code Online (Sandbox Code Playgroud)

请注意,使用Jackson Mix-in Annotations接口 )动态地从类中删除自定义反序列化器,避免了由于.DefaultJsonDeserializer POJOStackOverflowErrorobjectMapper.readValue(jsonParser, DataMapper.class)


然后,只需注释该类即可POJO

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

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


归档时间:

查看次数:

8299 次

最近记录:

6 年,8 月 前