应用场景
1、打印日志
把一个对象打印为json格式的字符串
log.info("入参,param:{}",JSON.toJSONString(param));
表面的需求,是打印字符串,本质的需求是把对象转换为json格式的字符串。
2、转换数据类型
比如,调用远程服务的时候,入参是json格式的字符串,json格式的字符串又细分为:
1、map
{key:value,key:value...} //对应fastjson里的JSONObject
2、list
[{key:value},{key:value}...] //对应fastjson里的JSONArray
具体需要什么数据,要看目标需求需要什么数据,无非就是两种:
1.map //对应fastjson里的JSONObject(实现了map,本质是map)
2.list //对应fastjson里的JSONArray(实现了list,本质是list)
确认了目标需求,然后剩下的,就是组装数据即可。
接口入参和出参设计
基于Http协议的接口,很多就是json格式的字符串。比如,公司风控接口,入参和参数就是基于http协议的json字符串。
步骤
1.组装数据,得到指定格式的数据
2.把指定格式的数据转换为json格式的字符串
总结
1.基于http协议的接口,入参和出参很多都是字符串。rpc协议则是对象,所以才需要二进制序列化和反序列化。
2.所谓的序列化,其实本质就是转换数据类型。只不过基于json的话,是json格式的字符串和对象互转;而rpc协议,则是对象和二进制互转。
对象转换为json格式的字符串
入参是任何类型的对象
JSON.toJSONString(Object object)
json格式的字符串转换为对象
入参是String类型;出参是fastjson里的对象类型,比如JSONObject/JSONArray,也可以是List类型。
JSON.parseObject(json格式的字符串,实体类.class)
出参是List类型。
public static <T> List<T> parseArray(String text, Class<T> clazz)
出参是map类型
//第一种方式
Map maps = (Map)JSON.parse(str);
System.out.println("这个是用JSON类来解析JSON字符串!!!");
for (Object map : maps.entrySet()){
System.out.println(((Map.Entry)map).getKey()+" " + ((Map.Entry)map).getValue());
}
//第二种方式
Map mapTypes = JSON.parseObject(str);
System.out.println("这个是用JSON类的parseObject来解析JSON字符串!!!");
for (Object obj : mapTypes.keySet()){
System.out.println("key为:"+obj+"值为:"+mapTypes.get(obj));
}
//第三种方式
Map mapType = JSON.parseObject(str,Map.class);
System.out.println("这个是用JSON类,指定解析类型,来解析JSON字符串!!!");
for (Object obj : mapType.keySet()){
System.out.println("key为:"+obj+"值为:"+mapType.get(obj));
}
核心和本质
json库,是为了解决json问题,json有两个问题:
1、json格式的字符串
2、对象
这个是从数据类型的维度来看json问题的。
首先,这是给数据建模,即就是有这两种数据类型。
其他的,jar里所有的类,都是为了处理这两个数据类型互转。具体来说,就是不断地转换和组装这两种数据类型。
本质是根据
1.输入数据
2.输出数据
的要求,来进行转换和组装数据。
核心类
JSON
具体数据类型的类
1.map
JSONObject
2.list
JSONList
类继承图
JSONObject和map的区别?
没有任何区别。
都是map,只不过对map进行了增强,即速度更快的处理json数据。 JSONArray也一样,只不过对list进行增强,速度更快的处理json格式的数据。
如何使用?
对象和json格式的字符串,互相转换是可逆的。
Model model = new Model(); //任意类型的对象
String json = JSON.toJSONString(model); // serializes model to Json //对象转换为json格式的字符串
Model model2 = JSON.parseObject(json, Model.class); // deserializes json into model2 //json格式的字符串,再转换为对象
核心类
平常我们经常用到的是JSON.toJSONString()这个静态方法来实现序列化。其实JSON是一个抽象类,该类实现了JSONAware(转为json串)和JSONStreamAware(将json串写入Appendable中)的接口,同时又是JSONArray(内部实现就是个List)和JSONObject(内部实现就是个Map)的父类。JSON.toJSONString()方法内部实现基本相同,为做某些特定配置,对外暴露的接口可能不同。该方法的实现实际托付给了JSONSerializer类。
核心类的核心方法
同样是JSON类作为反序列化入口,实现了parse()、parseObject()、parseArray()等将json串转换为java对象的静态方法。这些方法的实现,实际托付给了DefaultJSONParser类。
DefaultJSONParser类相当于序列化的JSONSerializer类,是个功能组合器,它将上层调用、反序列化配置、反序列化实现、词法解析等功能组合在一起,相当于设计模式中的外观模式,供外部统一调用。同样,我们来分析该类的几个重要成员,看看他是如何实现纷繁的反序列化功能的。
JSONArray和JSONObject的组合使用
比如,入参是json格式的字符串(数组),那么,需要的是JSONArray,而JSONArray由多个JSONObject组成。
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject1 = new JSONObect();
jsonObject1.put("key1","value2");
jsonObject1.put("key2","value2");
jsonArray.add(jsonObject);
JSONObject jsonObject2 = new JSONObect();
jsonObject2.put("key1","value2");
jsonObject2.put("key2","value2");
jsonArray.add(jsonObject2);
HttpClient.调用远程方法(url,jsonArray.toString());
泛型
目标是获取list<任意实体对象>。
If the object that your are serializing/deserializing is a ParameterizedType (i.e. contains at least one type parameter and may be an array) then you must use the toJSONString(Object) or parseObject(String, Type, Feature[]) method. Here is an example for serializing and deserialing a ParameterizedType:
String json = "[{},...]";
Type listType = new TypeReference<List<Model>>() {}.getType();
List<Model> modelList = JSON.parseObject(json, listType);
参考
官方git首页
官方git-文档
文章
kimmking.github.io/2017/06/06/… //关于json和fastjson的全面介绍
blog.csdn.net/swust_chenp… //源码分析
www.csdn.net/article/201… //基本介绍
segmentfault.com/a/119000001… //demo代码