什么是JSON?
JSON(Java Script Object Notation,js对象简称)是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。简介和清晰的层次结构使得JSON成为理想的数据交互语言,也是日常前后端开发中数据的桥梁,也是前端和后端开发人员撕逼的主要内容,易于阅读和编写,并有效的提升网络传输效率。
在 JavaScript 语言中,一切都是对象。因此,任何JavaScript 支持的类型都可以通过 JSON 来表示,例如字符串、
- 对象表示为键值对,数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
JSON 键值对是用来保存 JavaScript 对象的一种方式,和 JavaScript 对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号 “” 包裹,使用冒号 : 分隔,然后紧接着值:
{"name": "QinJiang"}
{"age": "3"}
{"sex": "男"}
JSON和javaScript的关系:
JSON是JavaScript对象的字符串的表示,可以理解为对象在字符串层次的展开,它使用文本表示一个js对象的信息,本质是一个字符串。
var obj = {a:"章鱼";b:"八爪鱼"}//这是一个对象
var objStr = '{"a":"章鱼","b":"八爪鱼"}'; //这是一个json字符串,本质是一个字符串
JSON和JavaScript转换
JSON字符串转换为JavaScript对象 需要使用JSON.parse()方法
var obj = JSON.parse('{"a":"章鱼","b":"八爪鱼"}');
console.log(obj); //{a: "章鱼", b: "八爪鱼"}
JavaScript转换为JSON字符串,使用JSON.stringify()方法
var json = JSON.stringify({a: "章鱼", b: "八爪鱼"});
console.log(json);//{"a":"章鱼","b":"八爪鱼"}
后台测试
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency
ObjectMapper objectMapper = new ObjectMapper();
日常开发中都会封装一个操作json的工具类,其中ObjectMapper是jaskson的主要类,他提供一些功能将java对象和json匹配,反之使用JsonParse和JsonGenerator的实例实现Json实际的都/写,jackson还提供了功能十分便捷的注解,在开发中如果运用得当会方便很多。
ObjectMapper中常用的方法
-
readValue() 字符串转对象 转化目标实体类的属性要与被转JSON字符串总的字段 一 一对应!字符串里可以少字段,但绝对不能多字段,转化对象必须包含无参构造
ObjectMapper objectMapper = new ObjectMapper(); String userJson = "{ \"name\" : \"张三\", \"age\" : 5,\"sex\" : \"男\"}"; User user = objectMapper.readValue(carJson, User.class); System.out.println(user.toString()); //输出结果User{name='张三', age=5, sex='男'}
需要抛出IO异常 throws IOException (ps:这里为什么需要抛出IO异常,jakson底层通过io实现吗?)
-
writeValueAsString() java对象转成json字符串对象
System.out.println(objectMapper.writeValueAsString(user)); //输出{"name":"张三","age":5,"sex":"男"}
-
Map,list转json字符串
Map map=new HashMap(); String json=mapper.writeValueAsString(map); List<User> list = new ArrayList<>(); list.add(user); objectMapper.writeValueAsString(list);
objectMapper还支持 文件,输入,输出流
-
**writeValue()**输出到文件
objectMapper.writeValue(new File("friend.json"), friend);
-
writeValueAsBytes()写为字节流
byte[] bytes = objectMapper.writeValueAsBytes(friend); Friend newFriend = objectMapper.readValue(bytes, Friend.class); //从字节流中读取 newFriend = objectMapper.readValue(new File("friend.json"), Friend.class);//从文件中读取
集合的映射
除了使用Java类进行映射之外,我们还可以直接使用Map和List等Java集合组织JSON数据,在需要的时候可以使用readTree方法直接读取JSON中的某个属性值。需要注意的是从JSON转换为Map对象的时候,由于Java的类型擦除(Java的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息),所以类型需要我们手动用new TypeReference 给出。
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> map = new HashMap<>();
map.put("name","章鱼");
map.put("age",25);
map.put("array",new String[]{"hello","world"});
String jsonStr = mapper.writeValueAsString(map);
Map<String, Object> map1 = mapper.readValue(jsonStr,new TypeReference<Map<String,Object>>(){});
System.out.println(map1);
JsonNode root = mapper.readTree(jsonStr);
String name = root.get("name").asText();
System.out.println(name);
int age = root.get("age").asInt();
System.out.println(age);
//获取数组 需要用JsonNode来接收
JsonNode array = root.get("array");
System.out.println(array.get(1));
System.out.println(jsonStr);
打印结果
{array=[hello, world], name=章鱼, age=25}
章鱼
25
"world"
{"array":["hello","world"],"name":"章鱼","age":25}
Process finished with exit code 0
常用的注解
-
@JsonIgnore 忽略此属性,比如password我并不想返回给前端,就可以添加此注解,属性就不会被Jackson序列化和反序列化。
-
@JsonFormat(pattern = “yy-MM-dd HH:mm:ss a”, locale = “zh”, timezone = “GMT+8”) 时间日期输出格式化。
-
**@JsonInclude(JsonInclude.Include.NON_NULL) ** 如果字段为null不返回该字段的数据。
-
**@JsonProperty(value = “user_name”) ** 注解指定一个属性用于JSON映射,默认情况下映射的JSON属性与注解的属性名称相同,不过可以使用该注解的
value
值修改JSON属性名,该注解还有一个index
属性指定生成JSON属性的顺序,如果有必要的话。 -
@JsonIgnoreProperties 注解是类注解,在序列化为json的时候 @JsonIgnoreProperties({“prop1”,“prop2”}) 则会忽略pro1和pro2这两个属性。
在JSON反序列化为java类的时候@JsonIgnoreProperties(ignoreUnknown = true) 会忽略所有没有getter和seteer的属性,该注解在java属性和json不匹配的时候很有用。
- @JsonUnwrapped(prefix=“user”) 把成员对象中的属性提升到自己的容器中。
- **@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = “id”) ** 作用于类或属性上,被用来在序列化/反序列化时为该对象或字段添加一个对象识别码,通常是用来解决循环嵌套的问题 在jpa中会经常出现这种问题。
- @JsonIgnoreType 也是类注解,会排除所有指定类型的属性。
xml映射
Person person= new Person("张宇","zhangyu",25, LocalDate.of(1997,2,17));
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.findAndRegisterModules();
xmlMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
String text = xmlMapper.writeValueAsString(person);
System.out.println(text);
输出结果
<Person>
<Name>张宇</Name>
<NickName>zhangyu</NickName>
<Age>25</Age>
<birthday>
<year>1997</year>
<month>FEBRUARY</month>
<dayOfMonth>17</dayOfMonth>
<monthValue>2</monthValue>
<chronology>
<id>ISO</id>
<calendarType>iso8601</calendarType>
</chronology>
<dayOfWeek>MONDAY</dayOfWeek>
<dayOfYear>48</dayOfYear>
<era>CE</era>
<leapYear>false</leapYear>
</birthday>
</Person>
SpringBoot中集成
Spring Boot对Jackson的支持非常完善,只要我们引入相应类库,Spring Boot就可以自动配置开箱即用的Bean。Spring自动配置的ObjectMapper(或者XmlMapper)作了如下配置,基本上可以适应大部分情况。
禁用了MapperFeature.DEFAULT_VIEW_INCLUSION
禁用了DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
禁用了SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
如果需要修改自动配置的ObjectMapper属性也非常简单,Spring Boot提供了一组环境变量,直接在application.properties文件中修改即可。
com.fasterxml.jackson.databind.DeserializationFeature|spring.jackson.deserialization.=true|false
com.fasterxml.jackson.core.JsonGenerator.Feature|spring.jackson.generator.=true|false
com.fasterxml.jackson.databind.MapperFeature|spring.jackson.mapper.=true|false
com.fasterxml.jackson.core.JsonParser.Feature|spring.jackson.parser.=true|false
com.fasterxml.jackson.databind.SerializationFeature|spring.jackson.serialization.=true|false
com.fasterxml.jackson.annotation.JsonInclude.Include|spring.jackson.default-property-inclusion=always|non_null|non_absent|non_default|non_empty
参考自文章https://blog.csdn.net/u011054333/article/details/80504154/