带
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); }}
使用
SimpleModule我们可以注册它并与使用
ObjectMapper:
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)); }}
印刷品:
{ "user" : { "height" : "10 m" }, "food" : { "temperature" : "50 C" }, "house" : { "width" : "10 m" }}
当然,您需要对其进行测试并处理所有极端情况,但以上示例显示了总体思路。以类似的方式,我们可以处理反序列化。我们需要实现custom
BeanDeserializerModifier和一个custom
UnitDeserialiser:
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; }}
反序列化器示例
int:
class UnitIntStdScalarDeserializer extends StdScalarDeserializer<Integer> { private StdScalarDeserializer<Integer> src; public UnitIntStdScalarDeserializer(StdScalarDeserializer<Integer> src) { super(src); this.src = src; } @Override public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String value = p.getValueAsString(); String[] parts = value.split("\s+"); if (parts.length == 2) { return Integer.valueOf(parts[0]); } return src.deserialize(p, ctxt); }}
上面的实现只是一个例子,应该针对其他原始类型进行改进。我们可以使用简单的模块以相同的方式注册它。重复使用与序列化相同:
unitModule.setDeserializerModifier(new UnitBeanDeserializerModifier());
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)