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

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


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


@JsonDeserialize(using = CustomBooleanJsonDeserializer.class)

private boolean active;

我也知道我可以在Spring默认值中注册一个模块(就像这里一样),但我只想将这些自定义反序列化程序用于这些特定的类。ObjectMapper


@Bean

public Module customDeserializersModule() {

    SimpleModule module = new SimpleModule();

    module.addDeserializer(Boolean.class, new CustomBooleanJsonDeserializer());

    // add other custom deserializers 

    return module;

}

我甚至知道我可以在中使用自定义,但我不想放弃通过 自动数据绑定的便利性,因为我必须防止其他人在没有必要的自定义反序列化程序的情况下使用它。ObjectMapperRestController@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


凤凰求蛊
浏览 124回答 2
2回答

慕运维8079593

您可以为类定义自定义反序列化程序(作为问题中的第二个想法),并在内部使用自己的自定义:ObjectMapperpublic class DataMapperJsonDeserializer extends JsonDeserializer<DataMapper> {&nbsp; &nbsp; private static final ObjectMapper objectMapper = new ObjectMapper();&nbsp; &nbsp; private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy");&nbsp; &nbsp; static {&nbsp; &nbsp; &nbsp; &nbsp; SimpleModule module = new SimpleModule();&nbsp; &nbsp; &nbsp; &nbsp; module.addDeserializer(BigInteger.class, new CustomBigIntegerJsonDeserializer());&nbsp; &nbsp; &nbsp; &nbsp; module.addDeserializer(BigDecimal.class, new CustomBigDecimalJsonDeserializer());&nbsp; &nbsp; &nbsp; &nbsp; module.addDeserializer(Boolean.class, new CustomBooleanJsonDeserializer());&nbsp; &nbsp; &nbsp; &nbsp; module.addDeserializer(String.class, new CustomStringJsonDeserializer());&nbsp; &nbsp; &nbsp; &nbsp; objectMapper.registerModule(module);&nbsp; &nbsp; &nbsp; &nbsp; objectMapper.addMixIn(DataMapper.class, DefaultJsonDeserializer.class);&nbsp; &nbsp; &nbsp; &nbsp; objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);&nbsp; &nbsp; &nbsp; &nbsp; objectMapper.setDateFormat(simpleDateFormat);&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public DataMapper deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {&nbsp; &nbsp; &nbsp; &nbsp; return objectMapper.readValue(jsonParser, DataMapper.class);&nbsp; &nbsp; }&nbsp; &nbsp; @JsonDeserialize&nbsp; &nbsp; private interface DefaultJsonDeserializer {&nbsp; &nbsp; &nbsp; &nbsp; // Reset default json deserializer&nbsp; &nbsp; }}请注意使用 Jackson 混合注释(接口)从类中动态删除自定义反序列化程序,从而避免堆栈溢出错误,否则由于 而会引发。DefaultJsonDeserializerPOJOobjectMapper.readValue(jsonParser, DataMapper.class)然后,只需注释类:POJO@JsonDeserialize(using = DataMapperJsonDeserializer.class)public class DataMapper implements Serializable {&nbsp; &nbsp; // It is not necessary to annotate each field with custom deserializers.}您甚至可以将其他类添加为 的字段,并且每种类型的自定义反序列化程序将自动应用于其字段,而无需注释。POJODataMapper

qq_遁去的一_1

您可以尝试将简单模块与上下文序列化程序接口一起使用。第一个可用于包装默认的去细节,第二个用于检查类型配置 - 检查注释。让我们从注释开始:@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@interface ForceCustomDeserializer {}我假设您只有一个给定类型的自定义实现,但如果它不是真正的,请扩展上面的注释并提供一些额外的信息,这些信息允许使用适当的去字符。例如,下面我们可以看到两个自定义的去序列化器,它们额外记录一些信息并运行默认的反序列化。使用基础去细节,因为如果您有一些额外的配置,我们不会松动它。class CustomBoolDeserializer extends StdScalarDeserializer<Boolean> implements ContextualDeserializer {&nbsp; &nbsp; private NumberDeserializers.BooleanDeserializer base;&nbsp; &nbsp; public CustomBoolDeserializer(NumberDeserializers.BooleanDeserializer base) {&nbsp; &nbsp; &nbsp; &nbsp; super(Boolean.class);&nbsp; &nbsp; &nbsp; &nbsp; this.base = base;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public Boolean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Custom BooleanDeserializer ....");&nbsp; &nbsp; &nbsp; &nbsp; return base.deserialize(p, ctxt);&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {&nbsp; &nbsp; &nbsp; &nbsp; Class<?> parent = property.getMember().getDeclaringClass();&nbsp; &nbsp; &nbsp; &nbsp; ForceCustomDeserializer annotation = parent.getAnnotation(ForceCustomDeserializer.class);&nbsp; &nbsp; &nbsp; &nbsp; return annotation == null ? base : this;&nbsp; &nbsp; }}class CustomStringDeserializer extends StringDeserializer implements ContextualDeserializer {&nbsp; &nbsp; private final StringDeserializer base;&nbsp; &nbsp; public CustomStringDeserializer(StringDeserializer base) {&nbsp; &nbsp; &nbsp; &nbsp; this.base = base;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Custom StringDeserializer ....");&nbsp; &nbsp; &nbsp; &nbsp; return base.deserialize(p, ctxt);&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {&nbsp; &nbsp; &nbsp; &nbsp; Class<?> parent = property.getMember().getDeclaringClass();&nbsp; &nbsp; &nbsp; &nbsp; ForceCustomDeserializer annotation = parent.getAnnotation(ForceCustomDeserializer.class);&nbsp; &nbsp; &nbsp; &nbsp; return annotation == null ? base : this;&nbsp; &nbsp; }}我们可以测试上面的自定义实现,如下所示:import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.databind.BeanDescription;import com.fasterxml.jackson.databind.BeanProperty;import com.fasterxml.jackson.databind.DeserializationConfig;import com.fasterxml.jackson.databind.DeserializationContext;import com.fasterxml.jackson.databind.JsonDeserializer;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;import com.fasterxml.jackson.databind.deser.ContextualDeserializer;import com.fasterxml.jackson.databind.deser.std.NumberDeserializers;import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;import com.fasterxml.jackson.databind.deser.std.StringDeserializer;import com.fasterxml.jackson.databind.module.SimpleModule;import java.io.File;import java.io.IOException;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;public class JsonApp {&nbsp; &nbsp; public static void main(String[] args) throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; File jsonFile = new File("./resource/test.json").getAbsoluteFile();&nbsp; &nbsp; &nbsp; &nbsp; SimpleModule forcedCustomModule = new SimpleModule();&nbsp; &nbsp; &nbsp; &nbsp; forcedCustomModule.setDeserializerModifier(new BeanDeserializerModifier() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (deserializer instanceof StringDeserializer) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // wrap with yours or return new deserializer&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new CustomStringDeserializer((StringDeserializer) deserializer);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (deserializer instanceof NumberDeserializers.BooleanDeserializer) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // wrap with yours or return new deserializer&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new CustomBoolDeserializer((NumberDeserializers.BooleanDeserializer) deserializer);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // override for other types&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return deserializer;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; ObjectMapper mapper = new ObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp; mapper.registerModule(forcedCustomModule);&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(mapper.readValue(jsonFile, Pojo.class));&nbsp; &nbsp; }}@ForceCustomDeserializerclass Pojo {&nbsp; &nbsp; private String name;&nbsp; &nbsp; private boolean bool;&nbsp; &nbsp; // getters, setters, toString}以上示例为以下有效负载:JSON{&nbsp; "name": "Jackson",&nbsp; "bool": true}指纹:Custom StringDeserializer ....Custom BooleanDeserializer ....Pojo{name='Jackson', bool=true}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java