关于 fastjson 的 @JSONField 注解的一些问题(详解)
fastjson 是一款非常优秀的 Java 序列化/反序列化框架,在序列化对象时使用 @JSONField 注解可以定义一些序列化和反序列化时的行为,本篇文章将详细讲解 @JSONField 注解的使用方法和一些注意事项。
基本用法
@JSONField 注解可以标注在类的属性上面,用于配置序列化和反序列化时的一些操作。以下为 @JSONField 注解的属性列表:
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
name | String | "" | 序列化或反序列化时的名称,如果不填写则使用属性名称 |
ordinal | int | -1 | 序列化时的顺序,从小到大排序。反序列化时忽略该属性 |
format | String | "" | 格式化输出,如日期格式化等 |
serialize | boolean | true | 是否序列化该属性 |
deserialize | boolean | true | 是否反序列化该属性 |
alternateNames | String[] | {} | 可选名称列表,序列化或反序列化时除了使用属性名称还可以使用列表中的其他名称 |
示例1:
public class User {
@JSONField(name = "userId", ordinal = 1)
private int id;
@JSONField(name = "userAge", format = "yyyy-MM-dd", ordinal = 3)
private Date birth;
@JSONField(serialize = false, deserialize = false)
private String password;
// getter 和 setter 略
}
在这个例子中,使用了 @JSONField 注解标注了用户 ID、出生日期和密码。其中,用户 ID 序列化后的名称是 userId,反序列化时依然使用该名称;该属性在序列化时的顺序是 1;出生日期序列化后的名称是 userAge,使用 yyyy-MM-dd 格式输出,序列化时的顺序是 3;密码属性在序列化和反序列化时都被忽略。
特殊用法
序列化指定对象类型
有些时候我们需要在序列化时指定对象的类型,此时可以通过 @JSONField 注解的 serializeUsing 属性来实现。
示例2:
public class Person {
@JSONField(serializeUsing = NameSerializer.class)
private String name;
// getter 和 setter 略
}
public class NameSerializer implements ObjectSerializer {
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
String value = (String)object;
if (value != null) {
serializer.write("【Name】" + value);
} else {
serializer.writeNull();
}
}
}
在这个例子中,Person 类中的 name 属性使用了 @JSONField 注解,并指定了它的序列化方式为 NameSerializer.class,也就是在序列化时调用 NameSerializer.write() 方法进行序列化。该方法在输出字符串前增加了 "【Name】" 前缀。
反序列化指定对象类型
有些时候我们需要在反序列化时指定对象的类型,这通常用于泛型类型等场景,此时可以通过 @JSONField 注解的 deserializeUsing 属性来实现。
示例3:
public class JsonVo<T> {
@JSONField(deserializeUsing = MyTypeReference.class)
T data;
// getter 和 setter 略
}
public class MyTypeReference implements ObjectDeserializer {
@Override
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
Class<T> clazz = TypeReference.rawType(type);
T object = parser.parseObject(clazz);
return object;
}
@Override
public int getFastMatchToken() {
return 0;
}
}
在这个例子中,JsonVo 类的 data 属性使用了 @JSONField 注解,并指定了它的反序列化方式为 MyTypeReference.class,也就是在反序列化时调用 MyTypeReference.deserialze() 方法进行反序列化。由于 JsonVo 类是一个泛型类,我们需要在 MyTypeReference.deserialze() 中通过 TypeReference.rawType() 方法获取到泛型的实际类型,并使用该类型进行反序列化。
总结
由于 @JSONField 注解可以配置序列化、反序列化时的各种属性,因此在实际的使用中可以根据需要自定义序列化和反序列化的行为,提高代码的灵活性和可扩展性。同时,在使用不当时也会带来一些意想不到的问题,因此在使用 @JSONField 注解时要格外注意。