【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包添加到类依赖中:

  1. jackson-annotations-2.9.8.jar
  2. jackson-core-2.9.8.jar
  3. jackson-databind-2.9.8.jar

注意:2.9.x 版本存在安全漏洞,建议使用2.10.x 以上版本。

3.使用ObjectMapper进行读写

我们可以使用ObjectMapperreadValue 方法将JSON内容反序列化为Java对象。同样,我们可也以使用ObjectMapperwriteValue 方法将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类的writeValueAsStringwriteValueAsBytes方法:

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);  
    }  
}
posted @   明小子@  阅读(504)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示