使用 Jackson 库进行对象映射

Beginner

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

在本实验中,我们将学习如何使用 Jackson 的 ObjectMapper 类将对象映射为 JSON,以及将 JSON 映射为对象。我们将使用一个名为 DemoClass 的简单 Java 类,并学习各种读取和写入 JSON 数据的技术。


Skills Graph

创建并编译 DemoClass

~/project 目录下创建一个新项目,并创建一个新的 DemoClass Java 类。将以下代码粘贴到 DemoClass.java 文件中。

import java.util.Date;

public class DemoClass {
    private String field1;
    private Double field2;
    private Date dateField;

    // 构造方法
    DemoClass() {}

    DemoClass(String field1, Double field2, Date dateField) {
        this.field1 = field1;
        this.field2 = field2;
        this.dateField = dateField;
    }

    // getters 和 setters
    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public Double getField2() {
        return field2;
    }

    public void setField2(Double field2) {
        this.field2 = field2;
    }

    public Date getDateField() {
        return dateField;
    }

    public void setDateField(Date dateField) {
        this.dateField = dateField;
    }
}

使用以下命令编译 DemoClass Java 类:

javac DemoClass.java

从 JSON 文件中读取对象

我们可以使用 ObjectMapper 类的 readValue() 方法将 JSON 文件中的数据读取到一个对象中。我们的 JSON 文件仅包含一个对象的属性-值对。

创建一个名为 demo.json 的新文件,并将以下 JSON 内容粘贴到其中。

{
    "field1": "Sample-1",
    "field2": 20.21,
    "dateField": "2021-07-30T14:20:30.000Z"
}

使用以下代码读取 JSON 文件并将其映射到 DemoClass 对象。

import java.io.File;
import java.text.SimpleDateFormat;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

public class ObjectMapperDemo {
    public static void main(String[] args) {
        try {
            String filePath = "demo.json";
            File file = new File(filePath);

            ObjectMapper objMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

            DemoClass obj = objMapper.readValue(file, DemoClass.class);

            System.out.println("Field1: " + obj.getField1());
            System.out.println("Field2: " + obj.getField2());
            System.out.println("DateField: " + obj.getDateField());
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

输出结果为:

Field1: Sample-1
Field2: 20.21
DateField: Fri Jul 30 14:20:30 UTC 2021

从 JSON 字符串中读取对象

我们可以将 JSON 字符串中的数据读取到一个对象中。我们将使用 ObjectMapper 类的 readValue() 方法。我们还需要向该方法传递 类类型

添加以下代码以从 JSON 字符串中读取数据。

String jsonString = "{\"field1\":\"Sample-1\",\"field2\":20.21,\"dateField\":\"2021-07-30T14:20:30.000Z\"}";

ObjectMapper objMapper = new ObjectMapper();
DemoClass obj = objMapper.readValue(jsonString, DemoClass.class);

System.out.println("Field1: " + obj.getField1());
System.out.println("Field2: " + obj.getField2());
System.out.println("DateField: " + obj.getDateField());

输出结果为:

Field1: Sample-1
Field2: 20.21
DateField: Fri Jul 30 14:20:30 UTC 2021

从 JSON URL 中读取对象

从 URL 中读取对象也非常简单。我们需要将 URL 对象和类类型传递给 readValue() 方法。

添加以下代码以从 JSON URL 中读取并映射对象。

import java.net.URL;
import java.text.SimpleDateFormat;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

public class ObjectMapperDemo {
    public static void main(String[] args) {
        try {
            URL jsonFileUrl = new URL("file:demo.json");
            ObjectMapper objMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            DemoClass obj = objMapper.readValue(jsonFileUrl, DemoClass.class);

            System.out.println("Field1: " + obj.getField1());
            System.out.println("Field2: " + obj.getField2());
            System.out.println("DateField: " + obj.getDateField());
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

输出结果与步骤 2 相同。

从 JSON 字符串数组读取到对象数组

假设一个字符串包含多个对象数据(以数组形式)的 JSON 格式。我们可以使用 ObjectMapper 类将这些数据读取到 DemoClass 类型的数组中。

添加以下代码以将 JSON 字符串数组中的数据读取到对象数组中。

String jsonString = " [{\"field1\":\"Sample-1\",\"field2\":20.21,\"dateField\":\"2021-07-30T14:20:30.000Z\"}," +
        " {\"field1\":\"Sample-2\",\"field2\":22.55,\"dateField\":\"2021-07-31T14:20:30.000Z\"}]";

ObjectMapper objMapper = new ObjectMapper();
DemoClass[] objectArr = objMapper.readValue(jsonString, DemoClass[].class);

for (DemoClass obj : objectArr) {
    System.out.println("Field1: " + obj.getField1());
    System.out.println("Field2: " + obj.getField2());
    System.out.println("DateField: " + obj.getDateField());
    System.out.println();
}

输出结果为:

Field1: Sample-1
Field2: 20.21
DateField: Fri Jul 30 14:20:30 UTC 2021

Field1: Sample-2
Field2: 22.55
DateField: Sat Jul 31 14:20:30 UTC 2021

从 JSON 字符串数组读取到对象列表

如果我们不希望将数据读取到固定大小的对象数组中,可以将对象读取到列表中。

添加以下代码以将 JSON 字符串数组中的数据读取到对象列表中。

String jsonString = " [{\"field1\":\"Sample-1\",\"field2\":20.21,\"dateField\":\"2021-07-30T14:20:30.000Z\"}," +
        " {\"field1\":\"Sample-2\",\"field2\":22.55,\"dateField\":\"2021-07-31T14:20:30.000Z\"}]";

ObjectMapper objMapper = new ObjectMapper();
ArrayList<DemoClass> objectList = objMapper.readValue(jsonString, new TypeReference<ArrayList<DemoClass>>(){});

for (DemoClass obj : objectList) {
    System.out.println("Field1: " + obj.getField1());
    System.out.println("Field2: " + obj.getField2());
    System.out.println("DateField: " + obj.getDateField());
    System.out.println();
}

输出结果与步骤 5 相同。

从 JSON 字符串数组读取到对象 Map

我们也可以将 JSON 字符串中的数据读取到一个 Map 中。类的每个属性将成为键,属性值将成为值。

添加以下代码以将 JSON 字符串数组中的数据读取到 Map 中。

String jsonString = "{\"field1\":\"Sample-1\",\"field2\":20.21,\"dateField\":\"2021-07-30T14:20:30.000Z\"}";

ObjectMapper objMapper = new ObjectMapper();
Map<String, Object> objectMap = objMapper.readValue(jsonString, new TypeReference<Map<String, Object>>() {});

for (Map.Entry<String, Object> entry : objectMap.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

输出结果为:

field1: Sample-1
field2: 20.21
dateField: 2021-07-30T14:20:30.000Z

将 JSON 读取为 JsonNode 对象

JsonNode 类为我们提供了一种更灵活的方式来解析 JSON。我们可以使用 ObjectMapper 类的 readTree() 方法将 JSON 读取为 JsonNode 对象。

添加以下代码以将 JSON 读取为 JsonNode 对象。

String jsonString = "{\"field1\":\"Sample-1\",\"field2\":20.21,\"dateField\":\"2021-07-30T14:20:30.000Z\"}";

ObjectMapper objMapper = new ObjectMapper();
JsonNode node = objMapper.readTree(jsonString);

System.out.println("Field1: " + node.get("field1").asText());
System.out.println("Field2: " + node.get("field2").asDouble());
System.out.println("DateField: " + node.get("dateField").asText());

输出结果与步骤 2 相同。

配置 ObjectMapper

我们可以配置 ObjectMapper,使其能够处理意外的输入。

添加以下代码以配置 ObjectMapper 忽略任何新属性。

String jsonString = "{\"field1\":\"Sample-1\",\"field2\":20.21,\"field3\":\"Unknown\"}";

ObjectMapper objMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
DemoClass obj = objMapper.readValue(jsonString, DemoClass.class);

System.out.println("Field1: " + obj.getField1());
System.out.println("Field2: " + obj.getField2());
System.out.println("DateField: " + obj.getDateField());

输出结果与步骤 2 相同。

处理日期

默认情况下,ObjectMapper 会将 java.util.date 映射为一个长整型值。这个长整型值表示自 1970 年 1 月 1 日以来经过的毫秒数。

添加以下代码以演示如何使用 SimpleDateFormat 定义日期格式来序列化 java.util.date

ObjectMapper objMapper = new ObjectMapper();

SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
objMapper.setDateFormat(dateFormat);

DemoClass obj = new DemoClass("Sample-1", 20.21, new Date());
String jsonString = objMapper.writeValueAsString(obj);

System.out.println(jsonString);

输出结果为:

{"field1":"Sample-1","field2":20.21,"dateField":"30-07-2021"}

总结

在本实验中,我们学习了如何使用 Jackson 的 ObjectMapper 类将对象映射为 JSON 以及将 JSON 映射为对象。我们学习了如何将 JSON 文件读取为对象、从 JSON 字符串中读取数据并将其映射为对象,以及如何从 JSON 字符串数组中读取对象到对象列表或数组中。我们还学习了如何将 JSON 字符串读取为 JsonNode 对象,并配置 ObjectMapper 以忽略新属性或基本类型的空值。最后,我们学习了如何处理日期,并在序列化 java.util.date 时使用特定的日期格式。