fastjson 和 jackson 学习

阅读: 评论:0

fastjson 和 jackson 学习

fastjson 和 jackson 学习

JSON学习

Json数据格式回顾

什么是json

JSON:(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript(欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。目前,Json处于数据交换语言的王者地位.

Json数组格式

Json的数据本身是数组,中括号包裹,数组的元素之间逗号分开.数组元素的数据类型没有限制.

var jsonArray = ["元素1","元素2","元素3"]; //定义数组格式json
console.log(jsonArray[0]); //访问json数组的元素
for(var i = 0 ; i < jsonArray.length ; i++){console.log(jsonArray[i]); //遍历数组,访问每个元素
}

Json对象格式

Json的数据本身是对象,大括号包裹.对象采用键值对形式存储,键固定为字符串类型,值是任意类型的数据.键和值使用冒号分开.

var jsonObject = {"k1":"v1","k2":"v2","k3":"v3"}; //定义对象格式json
console.log(jsonObject.k1); //取出键k1对应的值

数组对象相互嵌套格式

  1. 数组中的元素是对象

    var jsonArray = [{"k1":"v1"},{"k2":"v2"}
    ]; // 定义数组格式json,数组元素是对象
    console.log(jsonArray[0].k1); //访问数组0索引的元素,该元素的键k1对应的值
    
  2. 对象中的值是数组

    var jsonObject = {"k1":["元素1","元素2"],"k2":["元素1","元素2"]
    }; // 定义对象格式json,键是字符串类型,值是数组
    console.log(jsonObject.k1[0]); //访问对象的键是k1,对于的值为数组,数组的0索引元素
    
  3. 你中有我,我中有你

    var json = {"k1":["元素1",{"key1":"value1"},{"key2":"value2"}  ],"k2":[{"key1":"value1"}]
    }; //定义对象格式json,键是字符串,值是数组,数组的元素是对象
    console.log(json.k1[1].key1); //访问json对象的键k1,对应的是数组,访问数组的1索引,数组的1索引上的元素是对象,访问key1键对应的值
    

【1】FastJson

FastJson介绍

FastJson 是阿里巴巴的开源JSON解析库,它可以解析 JSON 格式的字符串,支持将 Java Bean 序列化为 JSON 字符串,也可以从 JSON 字符串反序列化到 JavaBean。

Fastjson 的优点

  • 速度快
    fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。
  • 使用广泛
    fastjson在阿里巴巴大规模使用,在数万台服务器上部署,fastjson在业界被广泛接受。在2012年被开源中国评选为最受欢迎的国产开源软件之一。
  • 测试完备
    fastjson有非常多的testcase,在1.2.11版本中,testcase超过3321个。每次发布都会进行回归测试,保证质量稳定。
  • 使用简单
    fastjson的 API 十分简洁。
  • 功能完备
    支持泛型,支持流处理超大文本,支持枚举,支持序列化和反序列化扩展。

前置准备工作:

准备了2个对象 JsonPojo , User

@Data
public class JsonPojo {private List<Integer> intList;private User user;private String address;private Map<Integer,String> map;
}
@Data
public class User {private String name;private String city;
}

① 对象—> 字符串

方法:

JSONString(object)

示例:

        JsonPojo pojo = new JsonPojo();User user = new User();user.setCity("湖北");user.setName("武汉");pojo.setUser(user);ArrayList<Integer> list = new ArrayList<>();list.add(1);list.add(2);pojo.setIntList(list);pojo.setAddress("大西安");HashMap<Integer, String> map = new HashMap<>();map.put(1,"1111");pojo.setMap(map);// 使用json序列化String s = JSONString(pojo);System.out.println("fastjson序列化结果:"+s);

字符串–> 对象

方法: 第2个参数是要转换为对象的类对象

// 将string解析为 对象
JsonPojo jsonPojo = JSON.parseObject(s, JsonPojo.class);

② list —> 字符串

String intString = JSONString(integerArrayList);

字符串—> list

这里有很多种方法来转.

private static void listTest() {ArrayList<Integer> integerArrayList = new ArrayList<>();integerArrayList.add(1);integerArrayList.add(3);// 3.1 方法一: list转stringString intString = JSONString(integerArrayList);System.out.println(intString);// 3.2 方法二: string 转回listList list1 = JSON.parseObject(intString, List.class);// 3.3 方法三: string --> list -- 借助TypeReferenceList<Integer> list2 = JSON.parseObject(intString, new TypeReference<List<Integer>>() {});// 3.4 方法四: string --> list List<Integer> list3 = JSONObject.parseArray(intString, Integer.class);// 3.5 方法五: string --> listList<Integer> list4 = JSONArray.parseArray(intString, Integer.class);
}

[注意] : 这里引入的TypeReference 是fastjson包下面的 import com.alibaba.fastjson.TypeReference;

③ map–> 字符串

String mapJson = JSONString(map);

字符串–> map

    private static void mapTest() {HashMap<Integer, String> map = new HashMap<>();map.put(1,"222");String mapJson = JSONString(map);System.out.println(mapJson);// 将string 转回 map -- 需要借助 TypeReference 来实现.// map对象中, 会有这个key是 int类型的. 就不是string了Map<Integer, String> mapObject = JSON.parseObject(mapJson, new TypeReference<HashMap<Integer, String>>(){});}

需要注意的是这里的 key 是 Integer 类型的, 我们看下它序列化之后是怎么样的???

结果: 打印如下 , 其中 1 仍然是 int类型的.

{1:"222"}

JSON层级关系

JSON 是一个抽象类, 有2个子类, 分别是 JSONArray + JSONObject

一个主要是负责对象类的一些API , 而另一个则是主要负责 数组一类的 API

JSONObject 对象使用

我们也可以使用 JSONObject 来获取我们想要的对象

我们可以看到 JSONObject 底层也是通过 map 来存储数据的。

我们可以把一个字符串转为 JSONObject 对象.

// 将string转为 JSONObject
JSONObject jsonObject = JSON.parseObject(s);

通过将java对象转为 JSONObject , 我们可以看到, 这里面只会有2类对象. 一类是 JSONObject , 另一类是 JSONArray , list 的对应的是 JSONArray , 其他的对应的是 JSONObject 类型的.

【特别注意的一点】: 我们可以看到这里面的一个map, 其中的一个元素, key是int类型的, 此时也被转化为了 string 类型了。

与之前的map --> 字符串进行比对, 可以发现, 之前直接转字符串时,map中如果key是integer时 ,那么会保留其 int属性,还是 1 , 而不是 “1”。

继续~~

我们可以直接从 JSONObject 这个对象中获取一些我们想要的数据。

跟map的语法一样, 通过key获取对应的value,分为2种,一种是获取的value是基本数据类型, 那么有对应的API

另一种则是获取的仍然是一个对象, 那么就拿到的还是一个 JSONObject .

value = 基本数据类型

value = 对象, 引用对象类型
JSONObject user1 = JSONObject("user");

如果你 getJSONObject(“key”) 拿到的是一个具体的值, 而不是一个对象, 那么拿 JSONObject 去接是会直接报错的, 因为类型不同, 当然拿这个方法去使用也是有问题的。

JSONArray 对象使用

后续补充~

【2】jackson

接下来介绍第二种常用的序列化与反序列化的方法

前言:

Jackson 于 2009 年 5 月首次正式发布,旨在满足快速、正确和轻量级三大宗旨。Jackson 是一个成熟稳定的库,它提供了多种不同的方法来处理 JSON,包括在一些简单的用例中使用注释。

Jackson 提供了三个核心模块。

Streaming ( jackson-core) 定义了一个低级流式 API 并包括特定于 JSON 的实现。
Annotations ( jackson-annotations) 包含标准的 Jackson 注释。
Databind( jackson-databind) 实现数据绑定和对象序列化。
将databind模块添加到项目中还会将流式处理和注释模块添加为传递依赖项。
————————————————
版权声明:本文为CSDN博主「西凉的悲伤」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:

maven依赖如下:

<dependency><groupId>com.</groupId><artifactId>jackson-annotations</artifactId><version>2.15.2</version>
</dependency>
<dependency><groupId>com.</groupId><artifactId>jackson-core</artifactId><version>2.15.2</version>
</dependency>
<dependency><groupId>com.</groupId><artifactId>jackson-databind</artifactId><version>2.15.2</version>
</dependency>

如果你是spring-boot项目,我们可以看到 它其中已经被动引入了这个依赖,因此也可以大概猜出来,spring使用的一些序列化的方式使用的是 jackson的序列化与反序列化。

@RequestBody  @ResponseBody 

这2个注解其中就含有将对象转为 json的作用,底层应该就是用的jackson将其序列化 和 反序列化的。

① 对象 --> 字符串

我们需要创建一个 ObjectMapper 对象 来进行序列化与反序列化的进行.

ObjectMapper mapper = new ObjectMapper();
String s = mapper.writeValueAsString(pojo);
    private static void objJackson() throws JsonProcessingException {JsonPojo pojo = new JsonPojo();User user = new User();user.setCity("湖北");user.setName("武汉");pojo.setUser(user);ArrayList<Integer> list = new ArrayList<>();list.add(1);list.add(2);pojo.setIntList(list);pojo.setAddress("大西安");HashMap<Integer, String> map = new HashMap<>();map.put(1,"1111");pojo.setMap(map);ObjectMapper mapper = new ObjectMapper();// 将对象--> json字符串String s = mapper.writeValueAsString(pojo);System.out.println(s);JsonPojo jsonPojo = adValue(s, JsonPojo.class);System.out.println(jsonPojo);}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

【注意】这里的1是 string 类型的,而不是 int 类型的,与fastjson的序列化这里是不一样的。需要注意。

字符串–> 对象

JsonPojo jsonPojo = adValue(s, JsonPojo.class);  // redaValue(string src, Class target)

第二个参数就是你想要转换为对象的class对象

和fastjson很像

② list --> 字符串

String s = mapper.writeValueAsString(list);

字符串 — > list

方法一: 感觉不太好
 // 没有指定list的泛型List jsonPojo = adValue(s, List.class);

可以看到结果是 反序列化后的结果中对象是以LinkedHashMap的形式存在的。

方法二: 感觉也不是很好, 有强转
// 可以通过先获取一个指定泛型的 list的 Reader
ObjectReader objectReader = aderForListOf(User.class);
List<User> users = (List<User>)adValue(s,User.class);
方法三: 借助 TypeReference --推荐

虽然fastjson 和 Jackson 都有 TypeReference , 但是并非来自于同一个包下面的. 它们都有各自的 TypeReference

// 指定反序列化的泛型 -- 借助 TypeReference
List<User> userList = adValue(s, new TypeReference<List<User>>() {
});

③ map --> string

还是一样的方法

String s = mapper.writeValueAsString(map);

字符串 --> map

// 方法一: 也是没有指定泛型
Map map1 = adValue(s, Map.class);// 方法二: 指定map泛型
Map<Integer, String> stringMap = adValue(s, new TypeReference<Map<Integer, String>>() {
});

JSONNode对象

Jackson之ObjectMapper对象的使用_jackson objectmapper-CSDN博客

        // 将string读取为 JsonNode 的2种方法.JsonNode jsonNode = adValue(s, JsonNode.class);JsonNode node = adTree(s);// 再从jsonnode对象中获取我们想要的对象

和 JSONObject 这个对象还是很像的.

【问题举例】

在前不久遇到的一个问题,发送http请求的时候,报了400。

以下是具体的代码。

ServiceA 去调用 ServiceB

ServiceA

    @GetMapping("/mapJson")public String mapJsonTest() throws IOException, URISyntaxException {HashMap<Integer, String> map = new HashMap<>();map.put(1,"1111");map.put(2,"222");map.put(3,"333");String request = httpService.sendRequest2(map);System.out.println(request);return request;}// 发送http请求public static String sendRequest2(Map<Integer, String> map) throws IOException {String url = "localhost:8080/mapJsonTest";HttpPut httpRequest = (HttpPut) buildHttpMethod(url);String userEntity = JSONString(map);StringEntity stringEntity = new StringEntity(userEntity, "UTF-8");httpRequest.setEntity(stringEntity);HttpResponse response = creatHttpClient().execute(httpRequest);int statusCode = StatusLine().getStatusCode();System.out.println(statusCode);HttpEntity entity = Entity();String result = Entity(), "UTF-8");return result;}

ServiceB

    @PutMapping("/mapJsonTest")public String method2(@RequestBody Map<Integer,String> map){Object o = (1);System.out.println(map);return "map 请求成功";}

然后就报400了, 不知道大家能看出什么问题吗?

这其中的问题就在于序列化和反序列化用的不是同一套东西, 我在反序列化的时候,用的是fastjson , 而对象在 @RequestBody 进行反序列化的时候使用的Jackson的这一套, 导致其中不匹配, 其中的具体的错误是:

ServiceB

2023-12-17 23:35:36.886  WARN 63116 --- [nio-8080-exec-1] .s.DefaultHandlerExceptionResolver : Resolved [org.verter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('1' (code 49)): was expecting double-quote to start field name; nested exception is com.JsonParseException: Unexpected character ('1' (code 49)): was expecting double-quote to start field name<EOL> at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 3]]

ServiceA

从提示中我们已经很明显的看出来了, 是因为其中一个字段的key是 int类型, 而服务B 期望的是 string类型, 类型不匹配导致的错误。

其实在上面写这个map转换的时候, 已经可以发现了这2处的不同之处,当然应该还有其他的不同之处。(注解也是不一样的)

解决办法

我们的最终目的是要让 map中的 int类型变为string类型即可。

方法一:JSONObject

我们上面使用到的 fastjson 的对象, JSONObject , 使用它来解决。

        String userEntity = JSONString(map);// 利用 jsonObject 进行中转一次。JSONObject jsonObject = JSON.parseObject(userEntity);String jsonString = JSONString(jsonObject);StringEntity stringEntity = new StringEntity(jsonString, "UTF-8");

仔细看下之前,我们用 JSON.parseObject(s) ; 的时候,就可以发现,它把这个int类型的key给你转为了 string类型,我们再转为string就可以了

我们可以明显看到2次的不一样。

转换之后是不会报错, 成功请求到。

方法二:jackson

那么就是使用同一套序列化和反序列化的方法啦 ,都使用jackson来序列化就好了,也不会有问题的。

这里面还有关于这2套序列化和反序列化的一个注解的坑,搜一下应该是可以看到的。

欢迎各位大佬交流讨论, 指出不足之处, 一起加油~~~

本文发布于:2024-01-31 05:32:21,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170665034425912.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:fastjson   jackson
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23