首页 >> 大全

JSON学习

2024-01-04 大全 26 作者:考证青年

JSON学习 Json数据格式回顾 什么是json

JSON:( , JS 对象简谱) 是一种轻量级的数据交换格式。它基于 (欧洲计算机协会制定的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对应的值

数组对象相互嵌套格式

数组中的元素是对象

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

对象中的值是数组

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

你中有我,我中有你

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

【1】 介绍

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

的优点

前置准备工作:

准备了2个对象 , 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;
}

① 对象—> 字符串

方法:

JSON.toJSONString(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 = JSON.toJSONString(pojo);System.out.println("fastjson序列化结果:"+s);

字符串–> 对象

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

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

② list —> 字符串

String intString = JSON.toJSONString(integerArrayList);

字符串—> list

这里有很多种方法来转.

private static void listTest() {ArrayList<Integer> integerArrayList = new ArrayList<>();integerArrayList.add(1);integerArrayList.add(3);// 3.1 方法一: list转stringString intString = JSON.toJSONString(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);
}

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

③ map–> 字符串

String mapJson = JSON.toJSONString(map);

字符串–> map

    private static void mapTest() {HashMap<Integer, String> map = new HashMap<>();map.put(1,"222");String mapJson = JSON.toJSONString(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 是 类型的, 我们看下它序列化之后是怎么样的???

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

{1:"222"}

JSON层级关系

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

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

对象使用

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

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

学习心得__学习的名言

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

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

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

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

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

继续~~

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

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

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

value = 基本数据类型

value = 对象, 引用对象类型

JSONObject user1 = jsonObject.getJSONObject("user");

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

对象使用

后续补充~

【2】

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

前言:

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

提供了三个核心模块。

( -core) 定义了一个低级流式 API 并包括特定于 JSON 的实现。

( -) 包含标准的 注释。

( -) 实现数据绑定和对象序列化。

将模块添加到项目中还会将流式处理和注释模块添加为传递依赖项。

————————————————

版权声明:本文为CSDN博主「西凉的悲伤」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:

maven依赖如下:

<dependency><groupId>com.fasterxml.jackson.coregroupId><artifactId>jackson-annotationsartifactId><version>2.15.2version>
dependency>
<dependency><groupId>com.fasterxml.jackson.coregroupId><artifactId>jackson-coreartifactId><version>2.15.2version>
dependency>
<dependency><groupId>com.fasterxml.jackson.coregroupId><artifactId>jackson-databindartifactId><version>2.15.2version>
dependency>

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

@RequestBody  @ResponseBody 

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

① 对象 --> 字符串

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

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 list = new ArrayList<>();list.add(1);list.add(2);pojo.setIntList(list);pojo.setAddress("大西安");HashMap 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 = mapper.readValue(s, JsonPojo.class);System.out.println(jsonPojo);}

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

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

字符串–> 对象

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

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

和很像

② list --> 字符串

String s = mapper.writeValueAsString(list);

_学习心得_学习的名言

字符串 — > list 方法一: 感觉不太好

 // 没有指定list的泛型List jsonPojo = mapper.readValue(s, List.class);

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

方法二: 感觉也不是很好, 有强转

// 可以通过先获取一个指定泛型的 list的 Reader
ObjectReader objectReader = mapper.readerForListOf(User.class);
List<User> users = (List<User>)objectReader.readValue(s,User.class);

方法三: 借助 --推荐

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

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

③ map -->

还是一样的方法

String s = mapper.writeValueAsString(map);

字符串 --> map

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

对象

之对象的使用 -CSDN博客

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

和 这个对象还是很像的.

【问题举例】

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

以下是具体的代码。

去调用

    @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 = "http://localhost:8080/mapJsonTest";HttpPut httpRequest = (HttpPut) buildHttpMethod(url);String userEntity = JSON.toJSONString(map);StringEntity stringEntity = new StringEntity(userEntity, "UTF-8");httpRequest.setEntity(stringEntity);HttpResponse response = creatHttpClient().execute(httpRequest);int statusCode = response.getStatusLine().getStatusCode();System.out.println(statusCode);HttpEntity entity = response.getEntity();String result = EntityUtils.toString(response.getEntity(), "UTF-8");return result;}

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

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

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

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

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

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

解决办法

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

方法一:

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

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

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

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

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

方法二:

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

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

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

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了