根据前面的FastJson的学习,我们已经掌握了FastJson的基础用法了,可以完成我们的日常开发了,今天我们来学习FastJson中的几个注解的用法
JSONField 介绍
注意:1、若属性是私有的,必须有set*方法。否则无法反序列化。
JSONField注解:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface JSONField {
// 配置序列化和反序列化的顺序,1.1.42版本之后才支持
int ordinal() default 0;
// 指定字段的名称
String name() default "";
// 指定字段的格式,对日期格式有用
String format() default "";
// 是否序列化
boolean serialize() default true;
// 是否反序列化
boolean deserialize() default true;
// 指定对该字段的特性
SerializerFeature[] serialzeFeatures() default {};
Feature[] parseFeatures() default {};
String label() default "";
boolean jsonDirect() default false;
// 指定使用的序列化类
Class<?> serializeUsing() default Void.class;
// 指定使用的反序列化的类
Class<?> deserializeUsing() default Void.class;
// 别名
String[] alternateNames() default {};
boolean unwrapped() default false;
}
JSONField 配置方式
可以配置在getter/setter方法或者字段上。例如:
配置在getter/setter上
public class User {
private int id;
private String name;
private String address;
@JSONField(name = "My_id")
public int getId() {
return id;
}
@JSONField(name = "My_id")
public void setId(int id) {
this.id = id;
}
省略了其他字段的set、get方法,toString方法
}
String json = "{'My_id':18,'name':'gakki'}";
User user = JSON.parseObject(json, User.class);
System.out.println(user);
String userStr = JSON.toJSONString(user);
System.out.println(userStr);
User{id=18, name='gakki', address='null'}
{"My_id":18,"name":"gakki"}
这里的@JSONField注解,就和GSON中的@SerializedName(value = “My_id”)一样,修改了反序列化的key。
@JSONField注解在set方法上:是反序列化的作用,@JSONField注解在get方法上:是序列化的作用。
去掉id的set上面的注解后:
public class User {
private int id;
private String name;
private String address;
@JSONField(name = "My_id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
省略了其他字段的set、get方法,toString方法
}
User{id=0, name='gakki', address='null'}
{"My_id":0,"name":"gakki"}
反序列化失败,因为json字符串中是My_id,不能和User中的id想匹配!
去掉id的get上面的注解后:
public class User {
private int id;
private String name;
private String address;
public int getId() {
return id;
}
@JSONField(name = "My_id")
public void setId(int id) {
this.id = id;
}
省略了其他字段的set、get方法,toString方法
}
User{id=18, name='gakki', address='null'}
{"id":18,"name":"gakki"}
可以看到,反序列化成功,序列化时还是使用的id!!!
配置在field上
和配置在set、get方法一样,只是配置在field上,相当于在set、get上面配置了,即:反序列化和序列化都起作用。
public class User {
@JSONField(name = "My_id")
private int id;
private String name;
private String address;
省略字段的set、get方法,toString方法
}
String json = "{'My_id':18,'name':'gakki'}";
User user = JSON.parseObject(json, User.class);
System.out.println(user);
String userStr = JSON.toJSONString(user);
System.out.println(userStr);
User{id=18, name='gakki', address='null'}
{"My_id":18,"name":"gakki"}
验证:当我们javaBean对象的属性使用:private修饰时,不配置set、get方法,看FastJson是否能正确的反序列化和序列化成功。
public class Person {
private int id;
private String name;
private String address;
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
String json = "{'id':18,'name':'gakki'}";
Person person = JSON.parseObject(json, Person.class);
System.out.println(person);
String s = JSON.toJSONString(person);
System.out.println(s);
Person{id=0, name='null', address='null'}
{}
发现,不配置私有属性的get和set方法,反序列化和序列化是失败的!!!
我们加上构造方法呢?
public class Person {
private int id;
private String name;
private String address;
public Person(int id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
Person{id=18, name='gakki', address='null'}
{}
发现,反序列化成功了,但是序列化失败了,加上构造方法后,就会使用构造方法来反序列化了,和加上set方法是同样的作用。
使用format配置日期格式化
public class Person {
private int id;
private String name;
private String address;
@JSONField(format="yyyyMMdd")
private Date birthday;
···
}
String json = "{'id':18,'name':'gakki','birthday':'20191222'}";
Person person = JSON.parseObject(json, Person.class);
System.out.println(person);
String s = JSON.toJSONString(person);
System.out.println(s);
Person{id=18, name='gakki', address='null', birthday=Sun Dec 22 00:00:00 CST 2019}
{"birthday":"20191222","id":18,"name":"gakki"}
可以看到,json字符串中的birthday字符串格式的日期,反序列化成功为Person对象中的Date类型,序列化时又变成了我们配置的格式。
使用serialize/deserialize指定字段不序列化
public class Person {
@JSONField(serialize = false)
private int id;
@JSONField(deserialize = false)
private String name;
private String address;
@JSONField(format = "yyyyMMdd")
private Date birthday;
public Person() {
}
···
}
String json = "{'id':18,'name':'gakki','birthday':'20191222'}";
Person person = JSON.parseObject(json, Person.class);
System.out.println(person);
String s = JSON.toJSONString(person,SerializerFeature.WriteMapNullValue);
System.out.println(s);
Person{id=18, name='null', address='null', birthday=Sun Dec 22 00:00:00 CST 2019}
{"address":null,"birthday":"20191222","name":null}
说明:id反序列化成功为18,但是禁止序列化,没有输出,name反序列化失败,允许序列化。
默认情况下:serialize 和 deserialize 都是 true。
注意:当你写了javaBean的有参的构造函数后,必须补全无参的构造函数!!!
如果,我们想指定某些属性为null序列化,其他为null的属性不序列化,该怎么办呢?
public class Person {
@JSONField(serialize = false)
private int id;
@JSONField(deserialize = false,serialzeFeatures = {SerializerFeature.WriteMapNullValue})
private String name;
private String address;
@JSONField(format = "yyyyMMdd")
private Date birthday;
public Person() {
}
···
}
public static void testPerson() {
String json = "{'id':18,'name':'gakki','birthday':'20191222'}";
Person person = JSON.parseObject(json, Person.class);
System.out.println(person);
String s = JSON.toJSONString(person);
System.out.println(s);
}
Person{id=18, name='null', address='null', birthday=Sun Dec 22 00:00:00 CST 2019}
{"birthday":"20191222","name":null}
这里,我们在name属性上,配置了:serialzeFeatures = {SerializerFeature.WriteMapNullValue 。
在JSON.toJSONString()时,没有配置SerializerFeature.WriteMapNullValue。此时只会当name为null时,才会输出null,address为null,不会输出。
JSON.toJSONString() 配置:SerializerFeature 是全局的作用,即所有的属性都起作用,对当个属性使用@JSONField注解来配置SerializerFeature只对当前的属性起作用。
使用ordinal指定字段的顺序
public class Person {
private int id;
private String name;
private String address;
@JSONField(format = "yyyyMMdd")
private Date birthday;
public Person() {
}
}
String json = "{'id':18,'name':'gakki','birthday':'20191222'}";
Person person = JSON.parseObject(json, Person.class);
System.out.println(person);
String s = JSON.toJSONString(person);
System.out.println(s);
Person{id=18, name='gakki', address='null', birthday=Sun Dec 22 00:00:00 CST 2019}
{"birthday":"20191222","id":18,"name":"gakki"}
此时序列化的顺序,应该是按照英文字母的顺序,birthday因为是b开头是最早的,所以序列化时排在第一位。
public class Person {
@JSONField(ordinal = 1)
private int id;
@JSONField(ordinal = 2)
private String name;
@JSONField(ordinal = 3)
private String address;
@JSONField(ordinal = 4,format = "yyyyMMdd")
private Date birthday;
public Person() {
}
}
Person{id=18, name='gakki', address='null', birthday=Sun Dec 22 00:00:00 CST 2019}
{"id":18,"name":"gakki","birthday":"20191222"}
此时,按照:ordinal给定的顺序来序列化,ordinal值越小越先被序列化。
这是:FastJson相对于GSON的优势,GSON中没有注解来配置序列化的顺序,必须重新配置序列化解析器来自定义顺序,比较麻烦。使用serializeUsing制定属性的序列化类
public class Person {
@JSONField(ordinal = 1)
private int id;
@JSONField(ordinal = 2, serializeUsing = NameSerialized.class)
private String name;
@JSONField(ordinal = 3)
private String address;
@JSONField(ordinal = 4, format = "yyyyMMdd")
private Date birthday;
public Person() {
}
}
单独给name属性配置序列化类:NameSerialized 【实现ObjectSerializer接口】
public class NameSerialized implements ObjectSerializer {
@Override
public void write(JSONSerializer jsonSerializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
System.out.println(object);
System.out.println(fieldName);
System.out.println(fieldType.getTypeName());
System.out.println(features);
jsonSerializer.write("你名字是");
}
}
String json = "{'id':18,'name':'gakki','birthday':'20191222'}";
Person person = JSON.parseObject(json, Person.class);
System.out.println(person);
String s = JSON.toJSONString(person);
System.out.println(s);
Person{id=18, name='gakki', address='null', birthday=Sun Dec 22 00:00:00 CST 2019}
gakki
name
java.lang.String
0
{"id":18,"name":"你名字是","birthday":"20191222"}
说明:write函数中,第一个参数是:jsonSerializer 序列化器,使用其来进行序列化的,第二个参数就是 name属性的值,第三个Object是 name属性的名字,第四个参数是name属性的类型,此处是String类型,第五个参数,features是序列化时的顺序,即:第几个被序列化的,此处是对name单独进行序列化的,所以是0。(默认是从0开始的)。
使用deserializeUsing制定属性的反序列化类
public class Person {
@JSONField(ordinal = 1, deserializeUsing = IdDeserialized.class)
private int id;
@JSONField(ordinal = 2)
private String name;
@JSONField(ordinal = 3)
private String address;
@JSONField(ordinal = 4, format = "yyyyMMdd")
private Date birthday;
public Person() {
}
}
IdDeserialized 实现:ObjectDeserializer 接口
public class IdDeserialized implements ObjectDeserializer {
@Override
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
System.out.println(type.getTypeName());
System.out.println(fieldName);
Object o = parser.parse(fieldName);
System.out.println(o);
Integer value = null;
if (o instanceof Integer) {
value = (Integer) o;
value += 20;
}
return (T) value;
}
@Override
public int getFastMatchToken() {
return 0;
}
}
String json = "{'id':20,'name':'gakki','birthday':'20191222'}";
Person person = JSON.parseObject(json, Person.class);
System.out.println(person);
String s = JSON.toJSONString(person);
System.out.println(s);
int
id
20
Person{id=40, name='gakki', address='null', birthday=Sun Dec 22 00:00:00 CST 2019}
{"id":40,"name":"gakki","birthday":"20191222"}
此时:id原来的值为:20,我们自定义的反序列化类将其加了20,最后反序列的值为:40。
一般,我们开发的过程中是不会随便修改传递过来的值,这里只是为了演示反序列化类的作用。
alternateNames 别名
public class Person {
@JSONField(alternateNames = {"my_id","My_id","MyId"})
private int id;
@JSONField()
private String name;
@JSONField()
private String address;
@JSONField(format = "yyyyMMdd")
private Date birthday;
}
String json = "{'id':18,'MyId':22,'My_id':24,'name':'gakki','birthday':'20191222'}";
Person person = JSON.parseObject(json, Person.class);
System.out.println(person);
String s = JSON.toJSONString(person);
System.out.println(s);
Person{id=24, name='gakki', address='null', birthday=Sun Dec 22 00:00:00 CST 2019}
{"birthday":"20191222","id":24,"name":"gakki"}
多个匹配时,以最后一个匹配为准,这里就是匹配了:My_id,最后输出为:24。
@JSONType 和 @JSONField类似,只是@JSONType作用与类上面而已。