【Jackson 】 - ObjectMapper对象详解
Jackson ObjectMapper对象详解
1.概述
本文将全面深入的学习Jackson ObjectMapper类,以及如何将Java对象序列化为JSON或者将JSON字符串反序列化为Java对象。
2.添加Jackson依赖
首先,在_pom.xml_中添加jackson依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.3</version>
</dependency>
如果不是maven项目,需要将以下jar包添加到类依赖中:
- jackson-annotations-2.9.8.jar
- jackson-core-2.9.8.jar
- jackson-databind-2.9.8.jar
注意:2.9.x 版本存在安全漏洞,建议使用2.10.x 以上版本。
3.使用ObjectMapper进行读写
我们可以使用ObjectMapper的readValue 方法将JSON内容反序列化为Java对象。同样,我们可也以使用ObjectMapper的writeValue 方法将Java对象序列化为JSON。
我们将使用下面的Car类对象作为实例来序列化或反序列化:
public class Car {
private String name;
private String color;
// standard getters setters
}
3.1.Java对象转JSON
使用_ObjectMapper_类的_writeValue_方法将Java对象序列到JSON文件中:
File resultFile = new File("target/car.json");
ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("BMW", "Black");
objectMapper.writeValue(resultFile, car);
上述实例输出结果是:
{"name":"BMW","color":"Black"}
如果希望将Java对象转换为字符串或字节数组,可以使用ObjectMapper
类的writeValueAsString
和writeValueAsBytes
方法:
String carAsString = objectMapper.writeValueAsString(car);
3.2. JSON转Java对象
使用_ObjectMapper_类将JSON字符串转换为Java对象:
@Test
public void jsonToJavaObject() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
String jsonString = "{\"name\":\"BMW\",\"color\":\"Black\"}";
Car car = objectMapper.readValue(jsonString, Car.class);
assertNotNull(car);
System.out.println(car);
}
readValue()函数还接受其他形式的输入,比如从JSON字符串的文件中读取数据:
@Test
public void jsonFileToJavaObject() throws Exception {
File resource = new File("target/car.json");
ObjectMapper objectMapper = new ObjectMapper();
Car car = objectMapper.readValue(resource, Car.class);
System.out.println(car);
}
或从网络获取JSON字符串文件:
@Test
public void fromURLToJavaObject() throws Exception {
URL resource = new URL("file:src/test/resources/json_car.json");
ObjectMapper objectMapper = new ObjectMapper();
Car car = objectMapper.readValue(resource, Car.class);
System.out.println(car);
}
3.3. JSON转JsonNode
可以将JSON解析为_JsonNode_对象,然后从JsonNode对象中获取数据:
@Test
public void jsonToJsonNode() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
String jsonString = "{\"name\":\"BMW\",\"color\":\"Black\"}";
JsonNode jsonNode = objectMapper.readTree(jsonString);
assertNotNull(jsonNode);
System.out.println(jsonNode);
System.out.println(jsonNode.get("name"));
System.out.println(jsonNode.get("name").asText());
}
// Output:{"name":"BMW","color":"Black"} “BMW" BMW
3.4. JSON数组字符串解析为Java List
使用_TypeReference_将数组形式的JSON解析为Java List:
@Test
public void jsonArrayToList() throws Exception {
String resourceJson = "[{ \"name\" : \"BMW\", \"color\" : \"Black\" }," +
" { \"name\" : \"toyota\", \"color\" : \"Red\" }]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> listCar = objectMapper.readValue(resourceJson, new TypeReference<List<Car>>() {
});
for (final Car car : listCar) {
System.out.println(car);
}
}
3.5. JSON字符串解析为Java Map
将JSON解析为Java Map:
@Test
public void jsonToMap() throws Exception {
String jsonString = "{\"name\":\"BMW\",\"color\":\"Black\"}";
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> map = objectMapper.readValue(jsonString, new TypeReference<Map<String, Object>>() {
});
System.out.println(map);
}
//{name=BMW, color=Black}
4.高级功能
Jackson库的最大优势之一就是高度可定制的序列化和反序列化。下面,我们将介绍一些高级功能。
4.1. 配置序列化或反序列化功能
将JSON对象转换为Java类时,如果JSON字符串中包含Java类中没有的字段,那么,默认解析过程将导致异常:
String jsonString = "{\"name\":\"BMW\",\"color\":\"Black\",\"price\":\"200000\"}";
上面示例的默认解析过程中,将导致_UnrecognizedPropertyException_异常。
通过configure方法,我们可以扩展默认解析过程以忽略新字段,解决以上异常:
@Test
public void failOnUnkownProperties() throws Exception {
String jsonCar = "{\"name\":\"BMW\",\"color\":\"Black\",\"price\":\"230000\"}";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Car car = objectMapper.readValue(jsonCar, Car.class);
System.out.println(car);
JsonNode jsonNodeRoot = objectMapper.readTree(jsonCar);
JsonNode jsonNodePrice = jsonNodeRoot.get("price");
String price = jsonNodePrice.asText();
System.out.println(price);
}
另一个选项是基于_FAIL_ON_NULL_FOR_PRIMITIVES的_,它定义了是否允许原始值为空值:
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
同样,_FAIL_ON_NUMBERS_FOR_ENUM_控制是否允许将枚举值序列化/反序列化为数字:
objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);
您可以在Jackson专辑中找到序列化和反序列化的相关文章。
4.2. 自定义序列化或反序列化
_ObjectMapper_类的另一个基本功能是能够自定义序列化器和反序列化器。当输入或输出的JSON结构和需要进行序列化或反序列化的Java类的结构不同时,自定义序列化器和反序列化器非常有用。
以下是自定义JSON序列化代码:
public class CustomCarSerializer extends StdSerializer<Car> {
public CustomCarSerializer() {
this(null);
}
public CustomCarSerializer(final Class<Car> t) {
super(t);
}
@Override
public void serialize( Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("name1: ", car.getName());
jsonGenerator.writeStringField("color1: ", car.getColor());
jsonGenerator.writeEndObject();
}
}
调用测试代码:
@Test
public void customSerializer() throws Exception {
ObjectMapper mapper = new ObjectMapper();
SimpleModule serializerModule = new SimpleModule("CustomSerializer", new Version(1, 0, 0, null, null, null));
serializerModule.addSerializer(Car.class, new CustomCarSerializer());
mapper.registerModule(serializerModule);
Car car = new Car("BMW", "Black");
String carJson = mapper.writeValueAsString(car);
System.out.println(carJson);
}
输出结果:
{"name1: ":"BMW","color1: ":"Black"}
以下是一个自定义JSON解析器示例:
public class CustomCarDeserializer extends StdDeserializer<Car> {
public CustomCarDeserializer() {
this(null);
}
public CustomCarDeserializer( Class<?> vc) {
super(vc);
}
@Override
public Car deserialize( JsonParser parser, DeserializationContext deserializer) throws IOException {
Car car = new Car();
ObjectCodec codec = parser.getCodec();
JsonNode node = codec.readTree(parser);
try {
JsonNode colorNode = node.get("color");
String color = colorNode.asText();
car.setColor(color);
} catch (final Exception e) {
Logger.debug("parse_exeption: unknown json.");
}
return car;
}
}
运行测试代码:
@Test
public void customDeserializer() throws Exception {
ObjectMapper mapper = new ObjectMapper();
SimpleModule deserializerModule = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null));
deserializerModule.addDeserializer(Car.class, new CustomCarDeserializer());
mapper.registerModule(deserializerModule);
Car car = mapper.readValue(EXAMPLE_JSON, Car.class);
System.out.println(car);
}
4.3. 处理日期格式
java.util.Date的默认序列化产生一个数字,即epoch时间戳(自1970年1月1日以来,以毫秒为单位,UTC)。但这不是我们日常生活中可读的,需要进一步的转换才能按照我们可读的格式显示。
在这里我们新建一个Student类来演示日期格式处理:
public class Student {
Car car;
Date birthday;
//省略 getters setters
}
我们希望将日期格式设置为yyyy-MM-dd HH:mm:ss ,测试代码如下:
@Test
public void dateFormat() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("BMW", "Black");
Student student = new Student();
student.setCar(car);
student.setBirthday(new Date());
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
objectMapper.setDateFormat(df);
String carAsString = objectMapper.writeValueAsString(student);
System.out.println(carAsString);
}
输出结果如下:
{"car":{"name":"BMW","color":"Black"},"birthday":"2020-05-18 13:56:15"}
要了解有关使用Jackson进行日期序列化的更多信息,请阅读我们更深入的文章。
4.4. 处理集合
DeserializationFeature类提供的另一个小而有用的功能是能够将JSON数组生成我们想要的集合类型。
例如,我们可以将结果生成为数组:
@Test
public void jsonArrayToJavaArray() throws Exception {
String jsonArray = "[{ \"name\" : \"BMW\", \"color\" : \"Black\" }," +
" { \"name\" : \"toyota\", \"color\" : \"Red\" }]";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
Car[] cars = objectMapper.readValue(jsonArray, Car[].class);
System.out.println(car);
}
或者时List:
@Test
public void jsonArrayToJavaList() throws Exception {
String jsonArray = "[{ \"name\" : \"BMW\", \"color\" : \"Black\" }," +
" { \"name\" : \"toyota\", \"color\" : \"Red\" }]";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
List<Car> listCar = objectMapper.readValue(jsonArray, new TypeReference<List<Car>>(){});
for (Car car : listCar) {
System.out.println(car);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix