现在开发中基本都使用json了, json的解析框架也是很多, 非常流行并且强烈推荐的还是 jackson
框架
该框架的出色之处我就不在列举了, 最最重要的是可以自定义序列化和反序列化的处理器
但是在项目中总会遇到各种特殊的解析或泛解析场景, 如题说所的获取字段类型的泛型类型
示例:
@Getter
@Setter
public class MyExpression<T> {
private Class<T> clz;
private T t;
private String expr;
public MyExpression() {
}
public MyExpression(String expr) {
this.expr = expr;
}
public MyExpression(Class<T> clz, String expr) {
this.clz = clz;
this.expr = expr;
}
}
@Getter
@Setter
public class MyReward implements Serializable {
private static final long serialVersionUID = 2670751308594930008L;
private int id;
private String name;
private String name2;
private MyExpression<Boolean> aaa;
private MyExpression<Long> bbb;
private MyExpression<Boolean> ccc;
}
ObjectMapper mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(MyExpression.class,new MyExpressionSerializer());
simpleModule.addDeserializer(MyExpression.class, new MyExpressionDeserializer());
//simpleModule.addDeserializer(String.class, new StringDeserializer());
mapper.registerModule(simpleModule);
如上代码, 我们想在解析的时候能够获取到 MyExpression<T>
这个T 到底是 Boolean 或是 Long
等具体类型
我们在序列化的时候可以将 对象字段直接变成 字符串
public class MyExpressionSerializer extends JsonSerializer<MyExpression> {
@Override
public void serialize(MyExpression value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
String expr = value.getExpr();
gen.writeString(expr);
}
}
同样, 我们需要将对应的json字符串,转换成 对象, 常规的泛序列化是只可以转换出具体的 内容, 但是无法获得具体的泛型类型 ?
参考网址: https://github.com/FasterXML/jackson-databind/issues/2711
@Slf4j
public class MyExpressionDeserializer extends JsonDeserializer<MyExpression>
implements ContextualDeserializer {
private Class clz;
@Override
public MyExpression deserialize(JsonParser jp, DeserializationContext context) throws IOException {
String expr = "deserialize---" + clz + " " + jp.getText().trim();
System.out.println(expr);
return new MyExpression<>(clz, expr);
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {
Class<?> rawClass = property.getType().containedTypeOrUnknown(0).getRawClass();
System.out.println(rawClass);
return new MyExpressionDeserializer(rawClass);
}
public MyExpressionDeserializer() {
}
public MyExpressionDeserializer(Class clz) {
this.clz = clz;
}
}
通过 实现 ContextualDeserializer
来实现泛型的获取
总结: 通过如上的示例代码, 我们可以在解析的时候维护我们所需要的参数, 这就给我们的解析工作带来了非常大的灵活性. 基本可以完成任何操作.
优化 可以将泛型类型存储到上下文中
@Slf4j
public class MyExpressionDeserializer extends JsonDeserializer<MyExpression> implements ContextualDeserializer {
@Override
public MyExpression deserialize(JsonParser jp, DeserializationContext context) throws IOException {
String expr = jp.getText().trim();
Object attribute = context.getAttribute(attribuateKey(jp.getParsingContext().getCurrentValue().getClass(),jp.getParsingContext().getCurrentName()));
return new MyExpression<>((Class) attribute, expr);
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {
Class<?> rawClass = property.getType().containedTypeOrUnknown(0).getRawClass();
ctxt.setAttribute(attribuateKey(property.getMember().getDeclaringClass(),property.getName()), rawClass);
return this;
}
private String attribuateKey(Class clz, String name) {
return String.format("%s#%s", clz.getName(), name);
}
}