Jackson常用操作
Jackson常用操作
导包
官方原生包
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
spring官网提供的整合包
spring官方提供的整合包跟原生包使用上没什么区别,只是更换了包名而已。spring官方默认的Json序列化就是使用Jackson。并且springboot starter web
默认就使用Jackson来做前端参数的json序列化。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
Jackson Json树模型
JsonNode
JsonNode
类,完整路径为com.fasterxml.jackson.databind.JsonNode
,是Jackson的json树模型(对象图模型)。JsonNode
是抽象类,我们是无法直接创建,并且通过JsonNode来改变json树里面的值。
JsonNode
的子类有:ObjectNode,TextNode,IntNode等等。所以在将JsonNode做转换为各种子类时要判断对象类型再进行转换。
ObjectNode
ObjectNode
类是JsonNode
的子类,可以对json树模型的节点进行写操作。
ObjectMapper objectMapper = new ObjectMapper();
String userJson = "{\"name\": \"jack\",\"age\": \"20\"}";
ObjectNode objectNode = objectMapper.valueToTree(new User("jack", 20));
//添加一个json k,v对
objectNode.put("xxx",123);
System.out.println(objectNode);
//遍历等等
objectNode.forEach(jsonNode -> {
System.out.println(jsonNode);
});
TextNode
TextNode
类是文本节点,TextNode
也是JsonNode
的子类。
IntNode
一个Int节点,IntNode
也是JsonNode
的子类。
一些要注意的方法
valueToTree
valueToTree
函数如下:
public <T extends JsonNode> T valueToTree(Object fromValue) throws IllegalArgumentException
valueToTree
返回的对象是泛型T
,并且该泛型T
继承于JsonNode
。如何确定valueToTree返回的值取决于你传的对象是字符串还是普通的Java对象。如:
当传入值为Java对象
//当传入普通Java对象时,返回值应该是ObjectNode
ObjectNode objectNode = objectMapper.valueToTree(new User("jack", 20));
//也可以使用JsonNode来接收(但是对象是ObjectNode,多态)
JsonNode jsonNode = objectMapper.valueToTree(new User("jack", 20));
当传入值为字符串
无论是否为Json格式的字符串,valueToTree都会返回TextNode对象
TextNode textNode = objectMapper.valueToTree("123");
//注意valueToTree方法如果输入的是字符串,返回的是TextNode,无论是否为Json格式的字符串
String userJson = "{\"name\": \"jack\",\"age\": \"20\"}";
TextNode textNode = objectMapper.valueToTree(userJson);
//也可以使用JsonNode来接收(但是对象是TextNode,多态)
JsonNode jsonNode = objectMapper.valueToTree(userJson);
readTree
readTree
返回的是JsonNode
,但是值得注意的是,跟valueToTree
相识,实际返回的对象不一定是ObjectNode
(JsonNode)。
返回对象是ObjectNode
String userJson = "{\"name\": \"jack\",\"age\": \"20\"}";
JsonNode jsonNode = objectMapper.readTree(userJson);
System.out.println(jsonNode.getClass()); //结果是:ObjectNode
返回对象是IntNode
String s = "123";
JsonNode jsonNode = objectMapper.readTree(s);
System.out.println(jsonNode.getClass()); //结果是:ObjectNode
其他返回类型为JsonNode的方法
Jackson有很多方法返回类型是JsonNode
,但是实际返回的是JsonNode
的子类,所以但其子类是无法直接强行转换的,所以在使用这些方法时,要做类型判断,判断属于哪个子类,然后在对JsonNode做类型转换,否则很有可能会抛出强转失败异常。
常用操作转换操作
JSON字符串->Java对象
ObjectMapper objectMapper = new ObjectMapper();
//字符串
String userJson = "{\"name\": \"jack\",\"age\": \"20\"}";
User user = objectMapper.readValue(userJson, User.class);
//文件
File file = new File("data/user.json");
User user = objectMapper.readValue(file, User.class);
//输入流
InputStream input = new FileInputStream("data/user.json");
User user = objectMapper.readValue(input, User.class);
//....
JSON数组字符串->Java对象数组
ObjectMapper objectMapper = new ObjectMapper();
String usersJson = "[{\"name\": \"jack\",\"age\": \"20\"},{\"name\": \"tom\",\"age\": \"21\"}]";
User[] users = objectMapper.readValue(usersJson, User[].class);
Arrays.stream(users).forEach(System.out::println);
JSON数组字符串->Java List
ObjectMapper objectMapper = new ObjectMapper();
String usersJson = "[{\"name\": \"jack\",\"age\": \"20\"},{\"name\": \"tom\",\"age\": \"21\"}]";
//转成普通的List(List里面其实LinkedHashMap)
List list = objectMapper.readValue(usersJson, List.class);
list.forEach(System.out::println);
//转成有泛型的List
List<User> users = objectMapper.readValue(usersJson, new TypeReference<List<User>>() {});
users.forEach(System.out::println);
JSON字符串->Java Map
ObjectMapper objectMapper = new ObjectMapper();
String userJson = "{\"name\": \"jack\",\"age\": \"20\"}";
//转成普通的Map(其实是Map<Object,Object>)
Map map = objectMapper.readValue(userJson, Map.class);
//转成带泛型约束的Map
Map<String, Object> user = objectMapper.readValue(userJson, new TypeReference<Map<String, Object>>() {});
JSON字符串->JsonNode
ObjectMapper objectMapper = new ObjectMapper();
String userJson = "{\"name\": \"jack\",\"age\": \"20\"}";
//对象其实是ObjectNode
JsonNode jsonNode = objectMapper.readTree(userJson);
//ObjectNode jsonNode = objectMapper.readTree(userJson);
JSON字符串->ObjectNode
String userJson = "{\"name\": \"jack\",\"age\": \"20\"}";
//如果传入的json字符串结构不完整,可能会解析成其他类型,而非ObjectNode
JsonNode jsonNode = objectMapper.readTree(userJson);
//必须是ObjectNode对象才能转
if (jsonNode instanceof ObjectNode){
ObjectNode objectNode = (ObjectNode)jsonNode;
}
字符串->TextNode
TextNode textNode = objectMapper.valueToTree("123");
//注意valueToTree方法如果输入的是字符串,返回的是TextNode,如果是对象,返回的是JsonNode
String userJson = "{\"name\": \"jack\",\"age\": \"20\"}";
TextNode textNode = objectMapper.valueToTree(userJson);
JsonNode->Java对象
User user = objectMapper.treeToValue(jack, User.class);
JsonNode->Json字符串
JsonNode jack = objectMapper.valueToTree(new User("jack", 20));
String s = jack.toString();
JsonNode->ObjectNode
//通过方法deepCopy()(只有引用指向的对象是ObjectNode才能拷贝)
if (jsonNode instanceof ObjectNode){
ObjectNode objectNode = jsonNode.deepCopy();
}
//或者直接参试强转(只有引用指向的对象是ObjectNode才能强转类型)
if (jsonNode instanceof ObjectNode){
ObjectNode objectNode = (ObjectNode)jsonNode;
}
JsonNode->TextNode
if (jsonNode instanceof TextNode){
TextNode textNode = (TextNode)jsonNode;
}
Java对象->JSON字符串
//Java对象转JSON字符串
String jack = objectMapper.writeValueAsString(new User("jack", 20));
//转二进制数组
byte[] jacks = objectMapper.writeValueAsBytes(new User("jack", 20));
//数组转JSON字符串
List<User> list = new ArrayList<>();
list.add(new User("jack",20));
list.add(new User("tom",21));
String s = objectMapper.writeValueAsString(list);
Java对象->JsonNode
JsonNode jack = objectMapper.valueToTree(new User("jack", 20));
Java对象->ObjectNode
//注意valueToTree方法如果输入的是字符串,返回的是TextNode,如果是对象,返回的是JsonNode
ObjectNode objectNode = objectMapper.valueToTree(new User("jack", 20));
填充忽略未知JSON字段
在使用JSON字段填充成Java对象时,可以选择是否忽略未知的字段,默认是不忽略的。那就代表了如果JSON字符串中有字段sex,而填充的对象中没有该字段,那么就会保存。
为了解决这个问题,jackson很贴心的可以让我们去选择进行字段填充的控制,可以设置为忽略未知JSON字段。
注解方式
可以在类的上方使用注解来声明该类的字段可以忽略@JsonIgnoreProperties(ignoreUnknown = true)
/**
* @author liangwy
* @since 2022-5-7
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private String name;
private Integer age;
}
代码配置方式
我们可以对ObjectMapper
进行配置,使其在填充时忽略未知字段。spring boot web就是使用忽略未知字段。
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
ObjectMapper配置
我们可以对ObjectMapper
对象进行配置来控制其行为。主要从一下三个方面进行配置:
SerializationFeature
:序列化特征(对象->JSON)DeserializationFeature
:反序列化特征(JSON->对象)JsonGenerator.Feature
:json生成器特征
官方文档位置:
【2.7.0 SerializationFeature API文档】
【2.7.0 DeserializationFeature API文档】
【2.7.0 JsonGenerator.Feature API文档】
//配置填充行为(忽略未知字段)
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
//配置浮点数反序列化为BIGDECIMAL类型
//If enabled such values will be deserialized as BigDecimals; if disabled, will be deserialized as Doubles.
objectMapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS,true);
n%2Fcore%2FJsonGenerator.Feature.html)
//配置填充行为(忽略未知字段)
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
//配置浮点数反序列化为BIGDECIMAL类型
//If enabled such values will be deserialized as BigDecimals; if disabled, will be deserialized as Doubles.
objectMapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS,true);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)