Java Jackson自定义序列化和反序列化
我无法找到用jackson实现自定义序列化/反序列化的正确方法。 我有很多类(~50个)都有原语字段,这些字段应该序列化/反序列化,而不是作为原语。 比如: 所有序列化和反序列化都非常相似,我只需要在整数(C、pages、meters等)后添加一个后缀 一种简单的方法是将一对Java Jackson自定义序列化和反序列化,java,json,jackson,Java,Json,Jackson,我无法找到用jackson实现自定义序列化/反序列化的正确方法。 我有很多类(~50个)都有原语字段,这些字段应该序列化/反序列化,而不是作为原语。 比如: 所有序列化和反序列化都非常相似,我只需要在整数(C、pages、meters等)后添加一个后缀 一种简单的方法是将一对@JsonSerialize/@JsonDeserialize注释放在每个这样的字段中并实现它们。 但我最终将使用100个非常类似的序列化器/反序列化器 我考虑将自定义注释添加到每个字段,比如@Units(“Degree”)
@JsonSerialize
/@JsonDeserialize
注释放在每个这样的字段中并实现它们。
但我最终将使用100个非常类似的序列化器/反序列化器
我考虑将自定义注释添加到每个字段,比如@Units(“Degree”)
或@Units(“Meters”)
,添加到这样的整数字段中,并实现一个序列化提供程序
,它将基于注释值以通用方式创建序列化程序。
但是我没有找到一个地方可以找到关于属性注释的信息。Idea with
Unit
注释非常好。我们只需要添加自定义com.fasterxml.jackson.databind.ser.BeanSerializerModifier
和com.fasterxml.jackson.databind.ser.BeanPropertyWriter
实现。让我们首先创建注释类:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Unit {
String value();
}
POJO
模型可能如下所示:
class Pojo {
private User user = new User();
private Food food = new Food();
private House house = new House();
// getters, setters, toString
}
class User {
@Unit("m")
private int height = 10;
// getters, setters, toString
}
class Food {
@Unit("C")
private int temperature = 50;
// getters, setters, toString
}
class House {
@Unit("m")
private int width = 10;
// getters, setters, toString
}
拥有所有这些,我们需要定制属性序列化:
class UnitBeanSerializerModifier extends BeanSerializerModifier {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
for (int i = 0; i < beanProperties.size(); ++i) {
final BeanPropertyWriter writer = beanProperties.get(i);
AnnotatedMember member = writer.getMember();
Unit units = member.getAnnotation(Unit.class);
if (units != null) {
beanProperties.set(i, new UnitBeanPropertyWriter(writer, units.value()));
}
}
return beanProperties;
}
}
class UnitBeanPropertyWriter extends BeanPropertyWriter {
private final String unit;
protected UnitBeanPropertyWriter(BeanPropertyWriter base, String unit) {
super(base);
this.unit = unit;
}
@Override
public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {
gen.writeFieldName(_name);
final Object value = (_accessorMethod == null) ? _field.get(bean) : _accessorMethod.invoke(bean, (Object[]) null);
gen.writeString(value + " " + unit);
}
}
unitModule.setDeserializerModifier(new UnitBeanDeserializerModifier());
印刷品:
{
"user" : {
"height" : "10 m"
},
"food" : {
"temperature" : "50 C"
},
"house" : {
"width" : "10 m"
}
}
当然,您需要对其进行测试并处理所有角落的情况,但上面的示例显示了总体思路。以类似的方式,我们可以处理反序列化。我们需要实现自定义BeanDeserializer
和一个自定义单元反序列化器
:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
SimpleModule unitModule = new SimpleModule();
unitModule.setSerializerModifier(new UnitBeanSerializerModifier());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(unitModule);
Pojo pojo = new Pojo();
System.out.println(mapper.writeValueAsString(pojo));
}
}
class UnitBeanDeserializerModifier extends BeanDeserializerModifier {
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
JsonDeserializer<?> jsonDeserializer = super.modifyDeserializer(config, beanDesc, deserializer);
if (jsonDeserializer instanceof StdScalarDeserializer) {
StdScalarDeserializer scalarDeserializer = (StdScalarDeserializer) jsonDeserializer;
Class scalarClass = scalarDeserializer.handledType();
if (int.class == scalarClass) {
return new UnitIntStdScalarDeserializer(scalarDeserializer);
}
}
return jsonDeserializer;
}
}
上面的实现只是一个示例,对于其他原语类型应该加以改进。我们可以使用简单的模块以同样的方式注册它。重复使用与序列化相同的内容:
class UnitBeanSerializerModifier extends BeanSerializerModifier {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
for (int i = 0; i < beanProperties.size(); ++i) {
final BeanPropertyWriter writer = beanProperties.get(i);
AnnotatedMember member = writer.getMember();
Unit units = member.getAnnotation(Unit.class);
if (units != null) {
beanProperties.set(i, new UnitBeanPropertyWriter(writer, units.value()));
}
}
return beanProperties;
}
}
class UnitBeanPropertyWriter extends BeanPropertyWriter {
private final String unit;
protected UnitBeanPropertyWriter(BeanPropertyWriter base, String unit) {
super(base);
this.unit = unit;
}
@Override
public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {
gen.writeFieldName(_name);
final Object value = (_accessorMethod == null) ? _field.get(bean) : _accessorMethod.invoke(bean, (Object[]) null);
gen.writeString(value + " " + unit);
}
}
unitModule.setDeserializerModifier(new UnitBeanDeserializerModifier());
您可以为所有实体注册通用序列化程序,它将读取正在序列化的实体并搜索
@Unit
注释,如果某个字段显示注释,则可以将其发送到自定义序列化程序以处理它(例如UnitsTypeAdapter
)。