2 回答
TA贡献1876条经验 获得超5个赞
您可以为类定义自定义反序列化程序(作为问题中的第二个想法),并在内部使用自己的自定义: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
}
}
请注意使用 Jackson 混合注释(接口)从类中动态删除自定义反序列化程序,从而避免堆栈溢出错误,否则由于 而会引发。DefaultJsonDeserializerPOJOobjectMapper.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.
}
您甚至可以将其他类添加为 的字段,并且每种类型的自定义反序列化程序将自动应用于其字段,而无需注释。POJODataMapper
TA贡献1725条经验 获得超7个赞
您可以尝试将简单模块
与上下文序列化程序接口一
起使用。第一个可用于包装默认的去细节,第二个用于检查类型配置 - 检查注释。
让我们从注释开始:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface ForceCustomDeserializer {
}
我假设您只有一个给定类型的自定义实现,但如果它不是真正的,请扩展上面的注释并提供一些额外的信息,这些信息允许使用适当的去字符。例如,下面我们可以看到两个自定义的去序列化器,它们额外记录一些信息并运行默认的反序列化。使用基础去细节,因为如果您有一些额外的配置,我们不会松动它。
class CustomBoolDeserializer extends StdScalarDeserializer<Boolean> implements ContextualDeserializer {
private NumberDeserializers.BooleanDeserializer base;
public CustomBoolDeserializer(NumberDeserializers.BooleanDeserializer base) {
super(Boolean.class);
this.base = base;
}
@Override
public Boolean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
System.out.println("Custom BooleanDeserializer ....");
return base.deserialize(p, ctxt);
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {
Class<?> parent = property.getMember().getDeclaringClass();
ForceCustomDeserializer annotation = parent.getAnnotation(ForceCustomDeserializer.class);
return annotation == null ? base : this;
}
}
class CustomStringDeserializer extends StringDeserializer implements ContextualDeserializer {
private final StringDeserializer base;
public CustomStringDeserializer(StringDeserializer base) {
this.base = base;
}
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
System.out.println("Custom StringDeserializer ....");
return base.deserialize(p, ctxt);
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {
Class<?> parent = property.getMember().getDeclaringClass();
ForceCustomDeserializer annotation = parent.getAnnotation(ForceCustomDeserializer.class);
return annotation == null ? base : this;
}
}
我们可以测试上面的自定义实现,如下所示:
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 {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
SimpleModule forcedCustomModule = new SimpleModule();
forcedCustomModule.setDeserializerModifier(new BeanDeserializerModifier() {
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
if (deserializer instanceof StringDeserializer) {
// wrap with yours or return new deserializer
return new CustomStringDeserializer((StringDeserializer) deserializer);
}
if (deserializer instanceof NumberDeserializers.BooleanDeserializer) {
// wrap with yours or return new deserializer
return new CustomBoolDeserializer((NumberDeserializers.BooleanDeserializer) deserializer);
}
// override for other types
return deserializer;
}
});
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(forcedCustomModule);
System.out.println(mapper.readValue(jsonFile, Pojo.class));
}
}
@ForceCustomDeserializer
class Pojo {
private String name;
private boolean bool;
// getters, setters, toString
}
以上示例为以下有效负载:JSON
{
"name": "Jackson",
"bool": true
}
指纹:
Custom StringDeserializer ....
Custom BooleanDeserializer ....
Pojo{name='Jackson', bool=true}
添加回答
举报