fastjson 使用详解

一. JSON

JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式

二. 主流框架介绍

2.1. Gson

  • Gson是目前功能最全的Json解析神器,Gson当初是为因应Google公司内部需求而由Google自行研发而来
  • 无依赖,不需要例外额外的jar,能够直接跑在JDK上。
  • 类里面只要有get和set方法,Gson完全可以将复杂类型的json到bean或bean到json的转换,是JSON解析的神器。
  • Gson在功能上面无可挑剔,但是性能上面比FastJson有所差距。

2.2. jackSon

  • Jackson所依赖的jar包较少,简单易用并且性能也要相对高些。

  • Jackson社区相对比较活跃,更新速度快。

  • Jackson对于复杂类型的json转换bean会出现问题,一些集合Map,List的转换出现问题。
  • Jackson对于复杂类型的bean转换Json,转换的json格式不是标准的Json格式

2.3. Fastjson:

  • Fastjson是一个Java语言编写的高性能的JSON处理器,由阿里巴巴公司开发。
  • 无依赖,不需要例外额外的jar,能够直接跑在JDK上。
  • FastJson在复杂类型的Bean转换Json上会出现一些问题,可能会出现引用的类型,导致Json转换出错,需要制定引用。
  • FastJson采用独创的算法,将parse的速度提升到极致,超过所有json库

2.4. 总结

综上三种Json技术的比较,在项目选型的时候可以使用Google的Gson和阿里巴巴的FastJson两种并行使用,
如果只是功能要求,没有性能要求,可以使用google的Gson,
如果有性能上面的要求可以使用Gson将bean转换json确保数据的正确,使用FastJson将Json转换Bean

三. Fastjson

一个JSON库涉及的最基本功能就是序列化和反序列化。Fastjson支持java bean的直接序列化。提供了com.alibaba.fastjson.JSON这个类进行序列化和反序列化。

3.1. 类型

3.1.1. 常用类型

  • JSON:fastJson的解析器,用于JSON格式字符串与JSON对象及javaBean之间的转换
  • JSONObject:fastJson提供的json对象 ,相当于Map < String, Object >
  • JSONArray:fastJson提供json数组对象 ,相当于List< Object >

3.1.3. JSONObject

JSONObject本质是实现了Map接口,因此可以直接向上转型给Map,JSONObject的数据是用 { } 来表示的

//示例json:{  "id" : "123", "courseID" : "huangt-test", "title" : "提交作业" }
public class JSONObject extends JSON implements Map<String, Object>

3.1.4. JSONArray

JSONArray 中是由JSONObject构成的数组,可以将

//示例json [{  "id" : "123", "courseID" : "huangt-test", "title" : "提交作业" }  ,  {  "content" : null, "beginTime" : 1398873600000  "endTime" } ] ; 

public class JSONArray extends JSON implements List<Object>
//举例代码

String json = "{\"name\":\"张三\",\"age\":20,\"some\":[{\"name\":\"张一\",\"age\":\"30\"},{\"name\":\"张二\",\"age\":\"10\"}]}";

//json字符串转换成jsonObject对象
JSONObject jso = JSON.parseObject(json);

//jsonobject对象取得some对应的jsonarray数组
JSONArray someList = jso.getJSONArray("some");

//jsonarray对象通过getjsonobjext(index)方法取得数组里面的jsonobject对象
JSONObject ao = someList.getJSONObject(0);

String str = ao.getString("name");
System.out.println(str);

3.2. 函数

3.2.1. 常用函数

//将JavaBean序列化为JSON文本(常用)
public static final String toJSONString(Object object);

//把JSON文本parse为JavaBean(常用)
public static final T parseObject(String text, Class clazz);

3.2.2. 其他函数


// 把JSON文本parse成JSONObject
public static final JSONObject parseObject(String text);

// 把JSON文本parse成JSONArray
 public static final JSONArray parseArray(String text);

//把JSON文本parse成JavaBean集合
public static final List parseArray(String text, Class clazz);

// 将JavaBean序列化为带格式的JSON文本
public static final String toJSONString(Object object, boolean prettyFormat);


// 把JSON文本parse为JSONObject或者JSONArray
public static final Objectparse(String text);


//将JavaBean转换为JSONObject或者JSONArray。
public static final Object toJSON(Object javaObject);

3.3. 序列化

3.3.1. 基本类型处理

int o =10;
//UseSingleQuotes 单引号
String json = JSON.toJSONString(o,SerializerFeature.UseSingleQuotes);
int k= JSON.parseObject(json,Integer.class);

System.out.println("json:"+json);
System.out.println("object:"+k);

3.3.2. 复杂类型处理

public class User{
    public String username="";
    public int id=0;
    public ArrayList<Link> link=null;
    public Map<String,Link> result=null;
}
class Link {
    public String name = "";
    public String phone = "";
}

//序列化和反序列化方法
//将Bean转换成json字符串
String str=JSON.toJSONString(user); 

//将json字符串转换为Bean
User user=JSON.parseObject(str,User.class);

3.3.3. 泛型处理

使用TypeReference将json串转成定义好的泛型对象

public class Result<T> {
    //some thing...
}

Result<User> obj = (Result<User>) JSON.parseObject(js, new TypeReference<Result<User>>(){});

3.4. 定制序列化

  • 通过@JSONField定制序列化
  • 通过@JSONType定制序列化
  • 通过SerializeFilter定制序列化
  • 通过ParseProcess定制反序列化

3.4.1. 通过@JSONField定制序列化

可以把@JSONField配置在字段或者getter/setter方法上

// 配置在字段上
public class Vo {

    @JSONField(name="ID")
    private Integer id;
}
// SerializeResult:{"ID":0}
// 配置在字段上
public class Vo {


    private Integer id;
    @JSONField(name="ID")
    public Integer getId() { return id;}
    //这里不一样
    @JSONField(name="IDs")
    public void setId(Integer value) {this.id = value;}
    //
}
// SerializeResult:{"IDs":0}
方法 描述
ordinal 指定字段的顺序
name 字段key值
format 配置日期格式化
serialize 指定字段是否序列化
deserialize 指定字段不序列化
serialzeFeatures 指定规则

3.4.2.通过@JSONType定制序列化

@JSONType与@JSONField区别在于,@JSONType是作用在类上的。

//配置序列化的时候,不序列化id  sex
@JSONType(ignores ={"id", "sex"}) 

// 配置序列化的时候,序列化name 和sex
@JSONType(includes={"name","sex"}) 

3.4.3 通过SerializeFilter定制序列化

通过SerializeFilter可以使用扩展编程的方式实现定制序列化。fastjson提供了多种SerializeFilter:

  • PropertyPreFilter 根据PropertyName判断是否序列化
  • PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化
  • NameFilter 修改Key,如果需要修改Key,process返回值则可
  • ValueFilter 修改Value
  • BeforeFilter 序列化时在最前添加内容
  • AfterFilter 序列化时在最后添加内容

以上的SerializeFilter在JSON.toJSONString中可以使用。

可以通过扩展实现根据object或者属性名称或者属性值进行判断是否需要序列化。例如:

  PropertyFilter filter = new PropertyFilter() {
      public boolean apply(Object source, String name Object value) {
          if ("id".equals(name)) {
              int id = ((Integer) value).intValue();
              return id >= 100;
          }
          return false;
        }
    };
    JSON.toJSONString(obj, filter); // 序列化的时候传filter

3.4.4 通过ParseProcess定制反序列化

ParseProcess是编程扩展定制反序列化的接口。fastjson支持如下ParseProcess:

  • ExtraProcessor 用于处理多余的字段
  • ExtraTypeProvider 用于处理多余字段时提供类型信息

使用ExtraProcessor 处理多余字段

public static class VO {
    private int id;
    private Map<String, Object> attributes = new HashMap<String, Object>();
    public int getId() { return id; }
    public void setId(int id) { this.id = id;}
    public Map<String, Object> getAttributes() { return attributes;}
}

ExtraProcessor processor = new ExtraProcessor() {
    public void processExtra(Object object, String key, Object value) {
        VO vo = (VO) object;
        vo.getAttributes().put(key, value);
    }
};

VO vo = JSON.parseObject("{\"id\":123,\"name\":\"abc\"}", VO.class, processor);
Assert.assertEquals(123, vo.getId());
Assert.assertEquals("abc", vo.getAttributes().get("name"));

使用ExtraTypeProvider 为多余的字段提供类型

public static class VO {
    private int id;
    private Map<String, Object> attributes = new HashMap<String, Object>();
    public int getId() { return id; }
    public void setId(int id) { this.id = id;}
    public Map<String, Object> getAttributes() { return attributes;}
}

class MyExtraProcessor implements ExtraProcessor, ExtraTypeProvider {
    public void processExtra(Object object, String key, Object value) {
        VO vo = (VO) object;
        vo.getAttributes().put(key, value);
    }

    public Type getExtraType(Object object, String key) {
        if ("value".equals(key)) {
            return int.class;
        }
        return null;
    }
};
ExtraProcessor processor = new MyExtraProcessor();

VO vo = JSON.parseObject("{\"id\":123,\"value\":\"123456\"}", VO.class, processor);
Assert.assertEquals(123, vo.getId());
Assert.assertEquals(123456, vo.getAttributes().get("value")); // value本应该是字符串类型的,通过getExtraType的处理变成Integer类型了。

问题

1. 如何处理超大JSON数组

先调用startArray函数,然后再遍历对象,最后调用endArray

//序列化
  JSONWriter writer = new JSONWriter(new FileWriter("/tmp/hello.json"));
  writer.startArray();
  for (int i = 0; i < 1000 * 1000; ++i) {
        writer.writeValue(new Model());
  }
  writer.endArray();
  writer.close();
//反序列化
JSONReader reader = new JSONReader(new FileReader("/tmp/hello.json"));
reader.startArray();
while (reader.hasNext()) {
    VO vo = reader.readObject(VO.class);
    System.out.println(vo);
}
reader.endArray();
reader.close();

2. 超大JSON对象处理

  //序列化
  JSONWriter writer = new JSONWriter(new FileWriter("/tmp/hello.json"));
  writer.startObject();
  for (int i = 0; i < 1000 * 1000; ++i) {
        writer.writeKey("x" + i);
        writer.writeValue(new VO());
  }
  writer.endObject();
  writer.close();
  //反序列化
  JSONReader reader = new JSONReader(new FileReader("/tmp/huge.json"));
  reader.startObject();
  while(reader.hasNext()) {
        String key = reader.readString();
        VO vo = reader.readObject(VO.class);
        //处理..
  }
  reader.endObject();
  reader.close();

3. 处理日期

fastjson处理日期的API很简单,例如:

JSON.toJSONStringWithDateFormat(date, "yyyy-MM-dd HH:mm:ss.SSS")

使用ISO-8601日期格式

JSON.toJSONString(obj, SerializerFeature.UseISO8601DateFormat);

全局修改日期格式

JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";
JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);

反序列化能够自动识别如下日期格式:

  • ISO-8601日期格式
  • yyyy-MM-dd
  • yyyy-MM-dd HH:mm:ss
  • yyyy-MM-dd HH:mm:ss.SSS
  • 毫秒数字
  • 毫秒数字字符串
  • .NET JSON日期格式
  • new Date(198293238)

4. 序列化不输出空值

使用SerializerFeature来输出空值

SerializerFeature 描述
WriteNullListAsEmpty 将Collection类型字段的字段空值输出为[]
WriteNullStringAsEmpty 将字符串类型字段的空值输出为空字符串 “”
WriteNullNumberAsZero 将数值类型字段的空值输出为0
WriteNullBooleanAsFalse 将Boolean类型字段的空值输出为false
//示例代码
String text = JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty);

猜你喜欢

转载自blog.csdn.net/qq_22989777/article/details/81218591