【json的处理】二、Jackson的处理
目前处理json的方法有很多,这里主要总结四种方法
1. Gson方式处理json 【json的处理】一、Gson处理
2. FastJson方式处理json 【json的处理】三、FastJson的处理
3. Jackson方式处理json 【json的处理】二、Jackson的处理
4. json-flattener方式处理json 【json的处理】四、json-flattener的处理
本文主要介绍Jackson的方式
前言
下面主要通过几个方面来介绍jackson:
1. jackson的一些常用方法
2. jackson的一些常用注解
3. JsonNode && ArrayNode && ObjectNode
4. jackson处理文件的导入导出
首先需要引入依赖
jackson-databind 依赖 jackson-core 和 jackson-annotations,当添加 jackson-databind 之后, jackson-core 和 jackson-annotations 也随之添加到 Java 项目工程中。在添加相关依赖包之后,就可以使用 Jackson。
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.11.0</version> </dependency>
一、jackson的一些常用方法
ObjectMapper是JSON操作的核心,Jackson的所有JSON操作都是在ObjectMapper中实现。
ObjectMapper有多个JSON序列化的方法,可以把JSON字符串保存File、OutputStream等不同的介质中。
writeValue(File arg0, Object arg1)把arg1转成json序列,并保存到arg0文件中。
writeValue(OutputStream arg0, Object arg1)把arg1转成json序列,并保存到arg0输出流中。
writeValueAsBytes(Object arg0)把arg0转成json序列,并把结果输出成字节数组。
//实体类 @Data @AllArgsConstructor public class TestUser { private String name; private Integer age; private Integer sex; private Date date; } //测试类 //定义一个对象用于测试 TestUser testUser = new TestUser("1",11,1,new Date()); TestUser testUser2 = new TestUser("2",22,2,new Date()); ObjectMapper mapper = new ObjectMapper(); //【对象转String】 String str = mapper.writeValueAsString(testUser); //结果:{"name":"1","age":11,"sex":1,"date":1600595735478} System.out.println(str); //【String转对象】这里要注意,版本号2.10.1以上readValue方法就会报错,2.9.5就可以 //报错信息:java.lang.ClassNotFoundException: com.fasterxml.jackson.core.exc.InputCoercionException TestUser testUserTemp = mapper.readValue(str, TestUser.class); //结果:TestUser(name=1, age=11, sex=1, date=Sun Sep 20 18:07:43 CST 2020) System.out.println(testUserTemp); //list转json-string List<TestUser> testUserList = new ArrayList<>(); testUserList.add(testUser); testUserList.add(testUser2); String json = mapper.writeValueAsString(testUserList); //结果:[{"name":"1","age":11,"sex":1,"date":1600910383747},{"name":"2","age":22,"sex":2,"date":1600910383747}] System.out.println(json);
二、jackson的一些常用注解
此注解用于属性上,作用是进行JSON操作时忽略该属性。
@JsonIgnoreProperties
此注解用于类上,作用是忽略多个属性,如:@JsonIgnoreProperties({"userName", "userAge"})
@JsonFormat
此注解用于属性上,作用是把Date类型直接转化为想要的格式,如@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")。
@JsonProperty
此注解用于属性上,作用是把该属性的名称序列化为另外一个名称,如把trueName属性序列化为name, @JsonProperty("name")。
@JsonInclude
此注解可用于属性和类上,作用是排除值为null的属性,如:
@JsonInclude(JsonInclude.Include.NON_NULL)-->属性为null不参与序列化。
@JsonInclude(JsonInclude.Include.NON_EMPTY)-->属性为空或者null都不参与序列化。
@JsonUnwrapped
此注解用于属性上,作用:
1. 是去掉外包装
2. 把成员对象中的属性提升到其容器类,并添加给定的前缀,如:@JsonUnwrapped(prefix = "user_")
@JsonAppend
此注解用于类上,为json添加虚拟属性,如:@JsonAppend(attrs = {@JsonAppend.Attr(value = "version")})
@JsonNaming
此注解用于类上,作用是将驼峰式改成下划线,如:
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
此外还有:
-
KEBAB_CASE: 属性名单词用短线分隔连接, 比如hello-world
-
LOWER_CASE: 属性名用小写字母而且没有分隔符, 比如helloworld
-
SNAKE_CASE: 属性名用小写字母而且用下划线做分隔符, 比如hello_world
-
UPPER_CAMEL_CASE: 属性名所有单词用大写开头而且没有分隔符, 比如HelloWorld
MapperFeature.USE_ANNOTATIONS
禁用所有jackson注解的功能
@JsonPropertyOrder
此注解用于类上,作用是给序列化之后的json排序,如:
1. JsonIgnore && JsonIgnoreProperties
@Data @AllArgsConstructor public class TestUser { @JsonIgnore private String name; private Integer age; private Integer sex; private Date date; } //定义一个对象用于测试 TestUser testUser = new TestUser("1",11,1,new Date()); ObjectMapper mapper = new ObjectMapper(); //【对象转String】 String str = mapper.writeValueAsString(testUser); //加上注解前:{"name":"1","age":11,"sex":1,"date":1600913752059} //加上注解后:{"age":11,"sex":1,"date":1600913711465} System.out.println(str); -------------------------------------------------------------------------------------------- @Data @AllArgsConstructor @JsonIgnoreProperties({"userName", "userAge"}) public class TestUser { private String userName; private Integer userAge; private Integer userSex; } //定义一个对象用于测试 TestUser testUser = new TestUser("111",11,1); ObjectMapper mapper = new ObjectMapper(); //【对象转String】 String str = mapper.writeValueAsString(testUser); //加上注解前:{"userName":"111","userAge":11,"userSex":1} //加上注解后:{"userSex":1} System.out.println(str);
2. JsonFormat
@Data @AllArgsConstructor public class TestUser { private String name; private Integer age; private Integer sex; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date date; } //定义一个对象用于测试 TestUser testUser = new TestUser("1",11,1,new Date()); ObjectMapper mapper = new ObjectMapper(); //【对象转String】 String str = mapper.writeValueAsString(testUser); //加上注解前:{"name":"1","age":11,"sex":1,"date":1600913893613} //加上注解后:{"name":"1","age":11,"sex":1,"date":"2020-09-24 02:17:56"} System.out.println(str);
3. JsonProperty
@Data @AllArgsConstructor public class TestUser { @JsonProperty("t_name") private String name; private Integer age; private Integer sex; private Date date; } //定义一个对象用于测试 TestUser testUser = new TestUser("1",11,1,new Date()); ObjectMapper mapper = new ObjectMapper(); //【对象转String】 String str = mapper.writeValueAsString(testUser); //加上注解前:{"name":"1","age":11,"sex":1,"date":1600913893613} //加上注解后:{"t_name":"1","age":11,"sex":1,"date":1600913990057} System.out.println(str);
4. JsonInclued
@Data @AllArgsConstructor public class TestUser { @JsonInclude(JsonInclude.Include.NON_NULL) private String name; private Integer age; private Integer sex; private Date date; } @Data @AllArgsConstructor @JsonInclude(JsonInclude.Include.NON_NULL) public class TestUser { private String name; private Integer age; private Integer sex; private Date date; } //定义一个对象用于测试 TestUser testUser = new TestUser(null,11,1,new Date()); ObjectMapper mapper = new ObjectMapper(); //【对象转String】 String str = mapper.writeValueAsString(testUser); //加上注解前:{"name":null,"age":11,"sex":1,"date":1600914468252} //加上注解后:{"age":11,"sex":1,"date":1600914452682} System.out.println(str);
5. JsonUnwrapped
@Data @AllArgsConstructor public class TestUser { private String name; private Integer age; private Integer sex; @JsonUnwrapped private Teacher teacher; } @Data @AllArgsConstructor public class Teacher { private String tel; private String email; } //定义一个对象用于测试 TestUser testUser = new TestUser("111",11,1,new Teacher("13718999090","12345@qq.com")); ObjectMapper mapper = new ObjectMapper(); //【对象转String】 String str = mapper.writeValueAsString(testUser); //加上注解前:{"name":"111","age":11,"sex":1,"teacher":{"tel":"13718999090","email":"12345@qq.com"}} //加上注解后:{"name":"111","age":11,"sex":1,"tel":"13718999090","email":"12345@qq.com"} System.out.println(str); ---------------------------------------------------------------------------------------------- @Data @AllArgsConstructor public class TestUser { private String userName; private Integer userAge; private Integer userSex; @JsonUnwrapped(prefix = "user_") private Teacher teacher; } //定义一个对象用于测试 TestUser testUser = new TestUser("111",11,1,new Teacher("11111","11111@qq.com")); ObjectMapper mapper = new ObjectMapper(); //【对象转String】 String str = mapper.writeValueAsString(testUser); //加上注解前:{"userName":"111","userAge":11,"userSex":1,"teacher":{"tel":"11111","email":"11111@qq.com"}} //加上注解后:{"userName":"111","userAge":11,"userSex":1,"user_tel":"11111","user_email":"11111@qq.com"} System.out.println(str);
6. JsonAppend
@Data @AllArgsConstructor @JsonAppend(attrs = {@JsonAppend.Attr(value = "version")}) public class TestUser { private String name; private Integer age; private Integer sex; } //定义一个对象用于测试 TestUser testUser = new TestUser("111",11,1); ObjectMapper mapper = new ObjectMapper(); //为虚拟属性添加值 ObjectWriter writer = mapper.writerFor(TestUser.class).withAttribute("version", "1.0"); //【对象转String】 String str = writer.writeValueAsString(testUser); //加上注解前:{"name":"111","age":11,"sex":1} //加上注解后:{"name":"111","age":11,"sex":1,"version":"1.0"} System.out.println(str);
7. JsonNaming
@Data @AllArgsConstructor @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) public class TestUser { private String userName; private Integer userAge; private Integer userSex; } //定义一个对象用于测试 TestUser testUser = new TestUser("111",11,1); ObjectMapper mapper = new ObjectMapper(); //【对象转String】 String str = mapper.writeValueAsString(testUser); //加上注解前:{"userName":"111","userAge":11,"userSex":1} //加上注解后:{"user_name":"111","user_age":11,"user_sex":1} System.out.println(str);
8. MapperFeature.USE_ANNOTATIONS
@Data @AllArgsConstructor @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) public class TestUser { private String userName; private Integer userAge; private Integer userSex; } //定义一个对象用于测试 TestUser testUser = new TestUser("111",11,1); ObjectMapper mapper = new ObjectMapper(); //禁用jackson注解 mapper.disable(MapperFeature.USE_ANNOTATIONS); //【对象转String】 String str = mapper.writeValueAsString(testUser); //加上注解前:{"userName":"111","userAge":11,"userSex":1} //加上注解后:{"userName":"111","userAge":11,"userSex":1} System.out.println(str);
9. JsonPropertyOrder
@Data @AllArgsConstructor @JsonPropertyOrder(value = {"userSex","userAge","userName"}) public class TestUser { private String userName; private Integer userAge; private Integer userSex; } //定义一个对象用于测试 TestUser testUser = new TestUser("111",11,1); ObjectMapper mapper = new ObjectMapper(); //【对象转String】 String str = mapper.writeValueAsString(testUser); //加上注解前:{"userName":"111","userAge":11,"userSex":1} //加上注解后:{"userSex":1,"userAge":11,"userName":"111"} System.out.println(str);
三、JsonNode && ArrayNode && ObjectNode
是对象结点,可以存入对象属性。如 { "name":"Lilei", "age":"18", "school":"HNU" }
ArrayNode
是数组结点,用于存放JsonNode数据。如[ "Lilei", "XiaoHong", {"nm1": "Jay", "nm2": "Kong"} ]
JsonNode
是ObjectNode和ArrayNode的父接口。想要生成JsonNode对象都要先生成ObjectMapper类对象,它是产生
String jsonStr = "{\"userName\":\"111\",\"userAge\":11,\"userSex\":1}"; ObjectMapper mapper = new ObjectMapper(); //【JsonNode】 JsonNode jsonNode = mapper.readTree(jsonStr); //结果:{"userName":"111","userAge":11,"userSex":1} System.out.println(jsonNode); //【判断值类型】 String nodeType = jsonNode.get("userName").getNodeType().toString()+"***"+jsonNode.get("userAge").getNodeType().toString(); //结果:STRING***NUMBER System.out.println(nodeType); //【遍历key】 Iterator<String> fieldNames = jsonNode.fieldNames(); while (fieldNames.hasNext()) { //结果:userName userAge userSex System.out.println(fieldNames.next()); } //【遍历value】 Iterator<JsonNode> elements = jsonNode.elements(); while (elements.hasNext()) { //结果:"111" 11 1 System.out.println(elements.next()); } //【单独获取某个key的值】 JsonNode path = jsonNode.get("userName"); //结果:"111" System.out.println(path); //结果:true System.out.println(jsonNode instanceof ObjectNode);
-
path:
路径访问安全,当访问的结点不存在时返回“MissingNode”,我将其理解为没有任何属性值的结点,也可以通过asText()转换为String类型,值为空字串;当访问的属性无效时同样返回空字串""。
优势是不知道多层子节点的值是否一定存在时可以连续使用path,若不存在一律返回"";但不能判断结点是否存在。
-
get:
路径访问不安全,其访问结点路径或属性无效时返回null,故使用连续使用get访问时,若路径不存在会出现空指针异常。
优势是可以用是否为null判断结点是否存在。
-
访问技巧:
不知道节点路径上是否所有节点都存在,可以使用
JsonNode temp = xxxNode.path("prop1").path("prop2").....get("propN");
String jsonStr = "{\"userName\":\"111\",\"userAge\":11,\"userSex\":1}"; ObjectMapper mapper = new ObjectMapper(); //【JsonNode】 JsonNode jsonNode = mapper.readTree(jsonStr); //【path】 JsonNode path = jsonNode.path("userName"); //结果:"111" System.out.println(path); JsonNode kkk = jsonNode.path("kkk"); //结果:空 System.out.println(kkk); //【连续path】 JsonNode paths = jsonNode.path("a").path("b").path("c"); //结果:空 System.out.println(paths); //【get】 JsonNode get1 = jsonNode.get("userName"); //结果:"111" System.out.println(get1); //结果:null JsonNode get2 = jsonNode.get("kkk"); System.out.println(get2); //【连续get】 JsonNode get3 = jsonNode.get("userName").get("kkk"); //结果:null System.out.println(get3); //【连续get-->如果get的结果为null之后继续get就会报错】 JsonNode get4 = jsonNode.get("userName").get("kkk").get("kkk"); //结果:java.lang.NullPointerException System.out.println(get4); //【asText && asInt】 String userName_userAgeText_userAgeInt = jsonNode.path("userName").asText()+"_"+jsonNode.path("userAge").asText()+"_"+jsonNode.path("userSex").asInt(); //结果:111_11_1 System.out.println(userName_userAgeText_userAgeInt);
2. ObjectNode
ObjectMapper mapper = new ObjectMapper(); //生成对象结点 ObjectNode objNode = mapper.createObjectNode(); //【put方法--在jdk1.8中,简单值用put设置】 objNode.put("name","111"); objNode.put("age",11); //结果:{"name":"111","age":11} System.out.println(objNode); //【set方法--在jdk1.8中,子节点用set设置】 ObjectNode objectNode = mapper.createObjectNode(); objectNode.put("innername", "222"); objectNode.put("innerage", 22); objNode.set("inner", objectNode); //结果:{"name":"111","age":11,"inner":{"innername":"222","innerage":22}} System.out.println(objNode);
3. ArrayNode
ObjectMapper mapper = new ObjectMapper(); //【生成数组结点】-->注意:数组结点添加元素不做简单值和结点类的区分 ArrayNode arrNode = mapper.createArrayNode(); arrNode.add("111"); //结果:["111"] System.out.println(arrNode); //生成对象结点 ObjectNode objNode = mapper.createObjectNode(); objNode.put("name","111"); objNode.put("age",11); ArrayNode addObj = arrNode.add(objNode); //结果:["111",{"name":"111","age":11}] System.out.println(addObj);
四、Jackson处理文件的导入导出
1. txt文件的导出
ObjectMapper mapper = new ObjectMapper(); //生成对象结点 ObjectNode objNode = mapper.createObjectNode(); objNode.put("name","111"); objNode.put("age",11); //【写入txt文件】 OutputStream outputStream= new FileOutputStream(new File("d:/11.txt")); mapper.writeValue(outputStream, objNode);
效果:
2. txt文件的导入
ObjectMapper mapper = new ObjectMapper(); //【导入txt文件数据】 JsonNode jsonNode = mapper.readTree(new File("d:/11.txt")); //结果:{"name":"111","age":11} System.out.println(jsonNode);
3. 导入导出案例
根据实体类对象的类型生成相应的json并导出
导入json数据
@Data @AllArgsConstructor public class TestUser { private String userName; private Integer userAge; private Integer userSex; private Integer[] test; } ObjectMapper mapper = new ObjectMapper(); //生成数组节点 ArrayNode arrayNode = mapper.createArrayNode(); arrayNode.add(1); arrayNode.add(2); arrayNode.add(3); //生成对象结点 ObjectNode objNode = mapper.createObjectNode(); objNode.put("userName","111"); objNode.put("userAge",11); objNode.put("userSex",1); objNode.put("test",arrayNode); //【导出】 OutputStream outputStream= new FileOutputStream(new File("d:/test.txt")); mapper.writeValue(outputStream, objNode); //【导入】 JsonNode jsonNode = mapper.readTree(new File("d:/test.txt")); TestUser testUser = mapper.treeToValue(jsonNode, TestUser.class); //结果:TestUser(userName=111, userAge=11, userSex=1, test=[1, 2, 3]) System.out.println(testUser);
效果:
参考:
1. https://www.cnblogs.com/jpfss/p/9055747.html
2. https://blog.csdn.net/wang_snake/article/details/93719178
持续更新!!!