一、依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.21</version>
</dependency>
二、FastJson序列化方式
PS:这里只陈述第一种方式。
- 通过@JSONField定制序列化-----配置在字段或者getter/setter方法上。
- 通过@JSONType定制序列化-----配置在类上
- 通过SerializeFilter定制序列化
- 通过ParseProcess定制反序列化
三、@JSONField
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})//一般作用在字段上
public @interface JSONField {
int ordinal() default 0;//配置序列化和反序列化的顺序
String name() default "";//配置序列化和反序列化时字段的名字
String format() default "";//字段格式化,对日期很有用
boolean serialize() default true;//是否序列化
boolean deserialize() default true;//是否反序列化
SerializerFeature[] serialzeFeatures() default {};//控制序列化的一些规则,如NULL的处理
Feature[] parseFeatures() default {};//控制反序列化的一些规则
String label() default "";
boolean jsonDirect() default false;//当有一个字段是字符串类型,里面是json格式数据,希望直接输入,而不是经过转义之后再输出。
Class<?> serializeUsing() default Void.class;//对某一个类的某个属性定制序列化
Class<?> deserializeUsing() default Void.class;//对某一个类的某个属性定制反序列化
String[] alternateNames() default {};//反序列化时使用多个不同的字段名称
}
- ordinal
@Data
public class User {
@JSONField(ordinal = 2)
private String name;
@JSONField(ordinal = 3)
private String sex;
@JSONField(ordinal = 1)
private Integer age;
}
//序列化结果:顺序为age、name、sex
{"age":20,"name":"zhangsan","sex":"男"}
- name
@Data
public class User {
@JSONField(ordinal = 2 , name="userName")
private String name;
@JSONField(ordinal = 3)
private String sex;
@JSONField(ordinal = 1)
private Integer age;
}
//序列化结果:name变为userName
{"age":20,"userName":"zhangsan","sex":"男"}
- format
@Data
public class User {
@JSONField(ordinal = 2 , name="userName")
private String name;
@JSONField(ordinal = 3 , format = "yyyy-MM-dd HH:mm:ss")
private Date birthDay;
@JSONField(ordinal = 1)
private Integer age;
}
//序列化结果:
{"age":20,"userName":"zhangsan","birthDay":"2018-11-05 18:26:46"}
- serialize
默认情况下,是true,也就是所有字段都会被序列化。
@Data
public class User {
@JSONField(ordinal = 2 , name="userName")
private String name;
@JSONField(ordinal = 3 , format = "yyyy-MM-dd HH:mm:ss")
private Date birthDay;
@JSONField(ordinal = 1 , serialize = false)
private Integer age;
}
//序列化结果:age没有被序列化
{"userName":"zhangsan","birthDay":"2018-11-05 18:29:19"}
- deserialize
@Data
public class User {
@JSONField(ordinal = 2 , name="userName")
private String name;
@JSONField(ordinal = 3 , format = "yyyy-MM-dd HH:mm:ss")
private Date birthDay;
@JSONField(ordinal = 1 , serialize = false)
private Integer age;
}
@Test
public void deserialize(){
String str = "{\"age\":20,\"userName\":\"zhangsan\",\"birthDay\":\"2018-11-05 18:26:46\"}";
User user = JSON.parseObject(str, User.class);
System.out.println(user);
}
//反序列化结果:
User(name=zhangsan, birthDay=Mon Nov 05 18:26:46 CST 2018, age=20)
- serialzeFreature
默认的序列化规则是当你的字段的值为null的时候,它是不会给你序列化这个字段的。我们可以通过serialzeFeatures的属性值SerializerFeature.WriteMapNullValue来控制,当属性的值为null时也输出该字段,字段的值为null。
@Data
public class User {
@JSONField(ordinal = 2 , name="userName")
private String name;
@JSONField(ordinal = 3 , format = "yyyy-MM-dd HH:mm:ss" , serialzeFeatures = SerializerFeature.WriteMapNullValue)
private Date birthDay;
@JSONField(ordinal = 1 , serialize = false)
private Integer age;
}
//JSON.toJSONString(user)序列化的结果:
{"userName":"zhangsan","birthDay":null}
//也可以如下使用,不在字段上做限制。这种情况针对所有字段。
@Test
public void test(){
User user = initUser();
String jsonStr = JSON.toJSONString(user , SerializerFeature.WriteMapNullValue,SerializerFeature.WriteNullNumberAsZero);
System.out.println(jsonStr);
}
//输出结果:
{"age":0,"userName":"zhangsan","birthDay":null}
当然SerializerFeature类中还有很多其他的属性:
名称 | 含义 |
QuoteFieldNames | 输出key时是否使用双引号,默认为true |
UseSingleQuotes | 使用单引号而不是双引号,默认为false |
WriteMapNullValue | 是否输出值为null的字段,默认为false |
WriteEnumUsingToString | Enum输出name()或者original,默认为false |
UseISO8601DateFormat | Date使用ISO8601格式输出,默认为false |
WriteNullListAsEmpty | List字段如果为null,输出为[],而非null |
WriteNullStringAsEmpty | 字符类型字段如果为null,输出为”“,而非null |
WriteNullNumberAsZero | 数值字段如果为null,输出为0,而非null |
- parseFeatures
略............
- jsonDirect
@Data
public class Group {
private String name;
@JSONField(jsonDirect = true)
private String userDetail;
}
@Data
public class User {
@JSONField(ordinal = 2 , name="userName")
private String name;
@JSONField(ordinal = 3 , format = "yyyy-MM-dd HH:mm:ss")
private Date birthDay;
@JSONField(ordinal = 1 )
private Integer age;
}
//测试
@Test
public void jsonDirect(){
User user = new User();
user.setName("zhangsan");
user.setBirthDay(new Date());
user.setAge(10);
String userJSON = JSON.toJSONString(user);
Group group = new Group();
group.setName("1组");
group.setUserDetail(userJSON);
String grouJson = JSON.toJSONString(group);
System.out.println(grouJson);
}
//输出结果:
{"name":"1组","userDetail":{"birthDay":"2018-11-05 19:16:18","userName":"zhangsan","age":10}}
//而不是:
{"name":"1组","userDetail":"{\"age\":10,\"userName\":\"zhangsan\",\"birthDay\":\"2018-11-05 19:18:33\"}"}
- serializeUsing
如果实体类某字段是String类型,但第三方的相同字段是Interger类型,那么,就需要我们传过去的JSON串中该字段作为key对应的值不可以带双引号。这种情况,也可以用此方法解决。
//实体类
@Data
public class User {
@JSONField(ordinal = 2 , name="userName")
private String name;
@JSONField(ordinal = 3 , format = "yyyy-MM-dd HH:mm:ss")
private Date birthDay;
@JSONField(ordinal = 1 , serializeUsing = ModelValueSerializer.class)
private Integer age;
}
//工具类---需要实现ObjectSerializer重写write方法
public class ModelValueSerializer implements ObjectSerializer {
@Override
public void write(JSONSerializer jsonSerializer, Object o, Object o1, Type type, int i) throws IOException {
Integer value = (Integer) o;
String text = value + "岁";
jsonSerializer.write(text);
}
}
//测试
@Test
public void test(){
User user = new User();
user.setName("zhangsan");
user.setBirthDay(new Date());
user.setAge(10);
String jsonStr = JSON.toJSONString(user);
System.out.println(jsonStr);
}
//结果:
{"age":"10岁","userName":"zhangsan","birthDay":"2018-11-05 19:26:24"}
- deserializeUsing
略.........................
- alternateNames
@Data
public class User {
@JSONField(ordinal = 2 , name="userName" ,alternateNames = {"userName","studentName"})
private String name;
@JSONField(ordinal = 3 , format = "yyyy-MM-dd HH:mm:ss")
private Date birthDay;
@JSONField(ordinal = 1 , serializeUsing = ModelValueSerializer.class)
private Integer age;
}
@Test
public void alternateNames(){
String jsonVal0 = "{\"age\":"10",\"name\":\"zhangsan\",\"birthDay\":\"2018-11-05 19:41:47\"}";
String jsonVal1 = "{\"age\":11,\"userName\":\"lisi\",\"birthDay\":\"2018-11-05 19:41:47\"}";
String jsonVal2 = "{\"age\":12,\"studentName\":\"wangwu\",\"birthDay\":\"2018-11-05 19:41:47\"}";
User obj0 = JSON.parseObject(jsonVal0, User.class);
System.out.println(obj0);
User obj1 = JSON.parseObject(jsonVal1, User.class);
System.out.println(obj1);
User obj2 = JSON.parseObject(jsonVal2, User.class);
System.out.println(obj2);
}
//输出结果:
User(name=null, birthDay=Mon Nov 05 19:41:47 CST 2018, age=10)
User(name=lisi, birthDay=Mon Nov 05 19:41:47 CST 2018, age=11)
User(name=wangwu, birthDay=Mon Nov 05 19:41:47 CST 2018, age=12)
发现,JSON串中如果是name的话,反序列化的话会是null。但如果是userName或者studentName的话,则会成功反序列化。
并且,JSON串中age的值是带引号的"10",也就是String类型,而User类中age是Interger类型,这样也可以反序列化成功。