fastjson是阿里提供的json操作的开源项目。特点是api简单,效率高。
fastjson操作
fastjson的大部分操作都可以通过JSON对象静态调用。
将对象转json字符串
这样就可以将object转成json字符串1
String jsonStr=JSON.toJSONString(object);
带有日期格式转化1
2public static String toJSONStringWithDateFormat(Object object, String dateFormat,
SerializerFeature... features) {
toJSONString方法还有很多重载方法,SerializeFilter可以用来过滤不需要转json字符串的字段。SerializerFeature配置序列化的特征。1
public static String toJSONString(Object object, SerializeFilter[] filters, SerializerFeature... features)
SerializeConfig 序列化时的配置,可以添加特点类型自定义的序列化。1
2
3
4public static String toJSONString(Object object, //
SerializeConfig config, //
SerializeFilter filter, //
SerializerFeature... features)
将json字符串转为对象
将字符串转成对象可以通过JSON.parseObject方法,该方法有许多重载,可以定制反序列化。
如果没有加需要转成的类型的化,就会把对象转化为JSONObject1
public static JSONObject parseObject(String text)
传入转化的class就会转成改对象1
public static <T> T parseObject(String text, Class<T> clazz)
通过TypeReference构造转化类型1
2
3
4public static <T> T parseObject(String text, TypeReference<T> type, Feature... features)
//将json转为带泛型的map对象
Map<String,String> map=JSON.parseObject(msg,new TypeReference<Map<String,String>>(String.class,String.class){},null);
ParserConfig可以用于添加特定类型的自定义反序列化,ParseProcess用于处理json字符串中存在,对象中没有的额外字段1
2public static <T> T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor,
int featureValues, Feature... features)
反序列化数组可以通过parseArray,也可以用parseObject1
public static <T> List<T> parseArray(String text, Class<T> clazz)
注解
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 |
WriteNullBooleanAsFalse | Boolean字段如果为null,输出为false,而非null |
SkipTransientField | 如果是true,类中的Get方法对应的Field是transient,序列化时将会被忽略。默认为true |
SortField | 按字段名称排序后输出。默认为false |
WriteTabAsSpecial | 把\t做转义输出,默认为false 不推荐 |
PrettyFormat | 结果是否格式化,默认为false |
WriteClassName | 序列化时写入类型信息,默认为false。反序列化是需用到 |
DisableCircularReferenceDetect | 消除对同一对象循环引用的问题,默认为false |
WriteSlashAsSpecial | 对斜杠’/’进行转义 |
BrowserCompatible | 将中文都会序列化为\uXXXX格式,字节数会多一些,但是能兼容IE 6,默认为false |
WriteDateUseDateFormat | 全局修改日期格式,默认为false。JSON.DEFFAULT_DATE_FORMAT = “yyyy-MM-dd”;JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat); |
DisableCheckSpecialChar | 一个对象的字符串属性中如果有特殊字符如双引号,将会在转成json时带有反斜杠转移符。如果不需要转义,可以使用这个属性。默认为false |
NotWriteRootClassName | 含义 |
BeanToArray | 将对象转为array输出 |
WriteNonStringKeyAsString | 含义 |
NotWriteDefaultValue | 含义 |
BrowserSecure | 含义 |
IgnoreNonFieldGetter | 含义 |
WriteEnumUsingName | 枚举类型通过名字转化 |
例子
自定义的枚举类型反序列化
fastjson默认提供的对枚举类型的反序列化的方式有两种
- 根据枚举的name
- 根据枚举的ordinal值
但是如果需要通过自定义的值反序列化成枚举,就需要自定义反序列化器。
如下面枚举,我想通过EnumValue接口返回的value值进行反序列化1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16interface EnumValue{
int value();
}
enum TestEnum implements EnumValue{
TEST1(1),
TEST2(2),
;
private int value;
TestEnum(int value){
this.value=value;
}
public int value() {
return value;
}
}
1 | class Bean{ |
通过下面代码直接序列化,int类型的值会自动用ordinal,ordinal从0开始 ,TestEnum枚举有2个,ordinal值从0-1,这里会发生ArrayIndexOutOfBoundsException1
2
3String jsonStr = "{\"id\":1,\"testEnum\":2}";
Bean bean = JSON.parseObject(jsonStr, Bean.class);
System.out.println(bean);
解决方法:
自定义反序列化
1 | class EnumValueDeserializer implements ObjectDeserializer { |
注册反序列化器
注册有三种方法
通过ParserConfig注册
1 | String jsonStr = "{\"id\":1,\"testEnum\":2}"; |
通过JSONType注解注册
1 | (deserializer = EnumValueDeserializer.class) |
#### 复写ParserConfig,替换掉默认的枚举反序列化器,这种方式是全局的,对所有枚举起作用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 class MyParserConfig extends ParserConfig{
public ObjectDeserializer getDeserializer(Class<?> clazz, Type type) {
ObjectDeserializer derializer;
if (clazz.isEnum()) {
Class<?> deserClass = null;
JSONType jsonType = clazz.getAnnotation(JSONType.class);
if (jsonType != null) {
deserClass = jsonType.deserializer();
try {
derializer = (ObjectDeserializer) deserClass.newInstance();
this.putDeserializer(type,derializer);
return derializer;
} catch (Throwable error) {
// skip
}
}
//这里替换了原来的反序列化器。
derializer = new EnumValueDeserializer();
return derializer;
}
return super.getDeserializer(clazz, type);
}
1 | String jsonStr = "{\"id\":1,\"testEnum\":2}"; |
反序列化不通过setter方法。
反序列化字段不通过setter方法时,可以使用Feature.SupportNonPublicField。
1 | Test obj = JSON.parseObject(msg, new TypeReference<Test>() { |
反序列化带有get方法的list字段
但是对于对象中带有get方法的list字段,fastjson的处理:
通过get方法获取list或map,如果是null不会处理。
以下带来。com.alibaba.fastjson.parser.deserializer.FieldDeserializer类 setValue方法片段。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23else if (Map.class.isAssignableFrom(method.getReturnType())) {
Map map = (Map) method.invoke(object);
if (map != null) {
if (map == Collections.emptyMap()
|| map.getClass().getName().startsWith("java.util.Collections$Unmodifiable")) {
// skip
return;
}
map.putAll((Map) value);
}
} else {
Collection collection = (Collection) method.invoke(object);
if (collection != null && value != null) {
if (collection == Collections.emptySet()
|| collection == Collections.emptyList()
|| collection.getClass().getName().startsWith("java.util.Collections$Unmodifiable")) {
// skip
return;
}
collection.clear();
collection.addAll((Collection) value);
}
}
所以以下例子反序列化出来的ids属性为null。1
2
3
4
5
6
7
8
9
10
11
12
13public class Test {
private int id;
private List<Integer> ids;
public int getId() {
return id;
}
public List<Integer> getIds() {
return ids;
}
}
1 | String msg="[" + |
解决方法
1 | //ParserConfig 构造函数中将fieldbased设置为true,开启只基于字段进行反序列化。 |
设置了fieldBased,反序列化处理来ids就有值了