java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java Jackson

从Java到JSON一起探索Jackson的魔力

作者:小新x

Jackson是一个用于处理JSON数据的开源Java库,这篇文章主要为大家介绍了Java是如何利用Jackson处理JSON数据的,感兴趣的小伙伴可以了解一下

引言

Jackson简介

Jackson是一个用于处理JSON数据的开源Java库。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写,同时也易于计算机解析和生成。在Java领域,Jackson已经成为处理JSON数据的事实标准库。它提供了丰富的功能,包括将Java对象转换为JSON字符串(序列化)以及将JSON字符串转换为Java对象(反序列化)。

Jackson主要由三个核心包组成:

为什么选择Jackson

尽管Java生态系统中有其他处理JSON数据的库(如Gson和JSON-java),但Jackson仍然是许多开发者的首选,原因包括:

综上所述,Jackson是一个强大且易于使用的库,值得Java开发者在处理JSON数据时使用。

Jackson的基本功能

Jackson库的核心功能是将Java对象转换为JSON字符串(序列化)以及将JSON字符串转换为Java对象(反序列化)。下面是这两个功能的详细介绍:

将Java对象转换为JSON字符串(序列化)

序列化是将Java对象转换为JSON字符串的过程。这在许多场景中非常有用,例如在将数据发送到Web客户端时,或者在将数据存储到文件或数据库时。Jackson通过ObjectMapper类来实现序列化。以下是一个简单的示例:

import com.fasterxml.jackson.databind.ObjectMapper;
public class Person {
    public String name;
    public int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public static void main(String[] args) {
        ObjectMapper objectMapper = new ObjectMapper();
        Person person = new Person("Alice", 30);
        try {
            String jsonString = objectMapper.writeValueAsString(person);
            System.out.println(jsonString); // 输出:{"name":"Alice","age":30}
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

将JSON字符串转换为Java对象(反序列化)

反序列化是将JSON字符串转换回Java对象的过程。这在从Web客户端接收数据或从文件或数据库读取数据时非常有用。同样,Jackson使用ObjectMapper类来实现反序列化。以下是一个简单的示例:

import com.fasterxml.jackson.databind.ObjectMapper;
public class Person {
    public String name;
    public int age;
    public Person() {
    }
    public static void main(String[] args) {
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = "{\"name\":\"Alice\",\"age\":30}";
        try {
            Person person = objectMapper.readValue(jsonString, Person.class);
            System.out.println("Name: " + person.name + ", Age: " + person.age); // 输出:Name: Alice, Age: 30
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这些示例展示了Jackson库的基本功能。接下来的部分将介绍如何使用Jackson库,包括添加依赖、创建Java对象模型以及使用ObjectMapper进行序列化和反序列化。

由于Jackson库的API非常多,这里无法一一详细介绍。我将为你提供一些主要的API和组件概览,以便于你更好地了解Jackson库。具体实现和使用方法,你可以参考官方文档和相关教程。

以下是Jackson库的一些主要API和组件:

1.ObjectMapper:这是Jackson库的核心类,用于序列化和反序列化操作。主要方法有:

2.JsonParser:用于从JSON数据源(如文件、输入流或字符串)解析JSON数据。主要方法有:

3.JsonGenerator:用于将JSON数据写入数据源(如文件、输出流或字符串缓冲区)。主要方法有:

4.JsonNode:用于表示JSON树模型中的节点,可以是对象、数组、字符串、数字等。主要方法有:

5.注解:Jackson提供了一系列注解来配置序列化和反序列化过程。一些常用注解包括:

这只是Jackson库API和组件的一个概览。如果你想深入了解具体的API和使用方法,请参考官方文档(github.com/FasterXML/jackson-docs )和相关教程。同时,实际编程过程中,根据具体需求学习和了解相应的API也是非常有效的方法。

使用Jackson的基本步骤

要开始使用Jackson,你需要遵循以下基本步骤:

添加依赖(Maven或Gradle)

首先,你需要将Jackson库添加到你的项目中。这可以通过Maven或Gradle来完成。以下是添加Jackson库的方法:

Maven

将以下依赖添加到你的pom.xml文件中:

<dependencies>
  <!-- Jackson core -->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.13.0</version>
  </dependency>
  <!-- Jackson databind -->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version>
  </dependency>
  <!-- Jackson annotations -->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.13.0</version>
  </dependency>
</dependencies>

Gradle

将以下依赖添加到你的build.gradle文件中:

dependencies {
    implementation 'com.fasterxml.jackson.core:jackson-core:2.13.0'
    implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.0'
    implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.0'
}

创建Java对象模型

在使用Jackson之前,你需要创建一个Java对象模型,该模型表示你要序列化和反序列化的JSON数据。例如,以下是一个表示Person的简单Java类:

public class Person {
    private String name;
    private int age;
    public Person() {
    }
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

在这个示例中,我们使用了一个简单的Java Bean(具有私有字段、公共构造函数和getter/setter方法的类)来表示Person对象。

使用ObjectMapper进行序列化和反序列化

使用ObjectMapper类,你可以轻松地将Java对象序列化为JSON字符串以及将JSON字符串反序列化为Java对象。以下是一个简单的示例:

序列化

import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
    public static void main(String[] args) {
        ObjectMapper objectMapper = new ObjectMapper();
        Person person = new Person("Alice", 30);
        try {
            String jsonString = objectMapper.writeValueAsString(person);
            System.out.println(jsonString); // 输出:{"name":"Alice","age":30}
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

反序列化

import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
    public static void main(String[] args) {
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = "{\"name\":\"Alice\",\"age\":30}";
        try {
            Person person = objectMapper.readValue(jsonString, Person.class);
            System.out.println("Name: " + person.getName() + ", Age: " + person.getAge()); // 输出:Name: Alice, Age: 30
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这些示例展示了如何使用Jackson库进行序列化和反序列化操作。在实际项目中,你可能需要根据需求对这些操作进行更多的配置和自定义,例如使用注解、自定义序列化器和反序列化器等。

高级特性

注解(如@JsonProperty, @JsonIgnore)

Jackson库提供了一系列注解,可以帮助你在序列化和反序列化过程中对字段和类进行配置。以下是一些常用注解的示例:

@JsonProperty 注解:

该注解用于指定 Java 属性与 JSON 属性之间的映射关系,常用的参数有:

value:用于指定 JSON 属性的名称,当 Java 属性和 JSON 属性名称不一致时使用。

access:用于指定该属性的访问方式,常用的取值有 JsonAccess.READ_ONLY(只读),JsonAccess.WRITE_ONLY(只写)和 JsonAccess.READ_WRITE(可读可写)。

public class Person {
    @JsonProperty(value = "name")
    private String fullName;
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String password;
    // getters and setters
}
Person person = new Person();
person.setFullName("John Smith");
person.setPassword("123456");
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(person);
// {"name":"John Smith"}
Person person2 = mapper.readValue(json, Person.class);
System.out.println(person2.getFullName());
// John Smith
System.out.println(person2.getPassword());
// null

@JsonIgnore 注解:

该注解用于禁用 Java 属性的序列化和反序列化,常用的参数有:

无参数。

public class Person {
    private String fullName;
    @JsonIgnore
    private String password;
    // getters and setters
}
Person person = new Person();
person.setFullName("John Smith");
person.setPassword("123456");
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(person);
// {"fullName":"John Smith"}
Person person2 = mapper.readValue("{\"fullName\":\"John Smith\",\"password\":\"123456\"}", Person.class);
System.out.println(person2.getFullName());
// John Smith
System.out.println(person2.getPassword());
// null

@JsonFormat 注解:

该注解用于指定 Java 属性的日期和时间格式,常用的参数有:

shape:用于指定日期和时间的格式,可选的取值有 JsonFormat.Shape.STRING(以字符串形式表示)和 JsonFormat.Shape.NUMBER(以时间戳形式表示)。

pattern:用于指定日期和时间的格式模板,例如 "yyyy-MM-dd HH:mm:ss"

public class Person {
    private String fullName;
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
    private Date birthDate;
    // getters and setters
}
Person person = new Person();
person.setFullName("John Smith");
person.setBirthDate(new Date());
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(person);
// {"fullName":"John Smith","birthDate":"2022-05-16 10:38:30"}
Person person2 = mapper.readValue(json, Person.class);
System.out.println(person2.getFullName());
// John Smith
System.out.println(person2.getBirthDate());
// Mon May 16 10:38:30 CST 2022

@JsonInclude 注解:

该注解用于指定序列化 Java 对象时包含哪些属性,常用的参数有:

value:用于指定包含哪些属性,可选的取值有 JsonInclude.Include.ALWAYS(始终包含)、JsonInclude.Include.NON_NULL(值不为 null 时包含)、JsonInclude.Include.NON_DEFAULT(值不为默认值时包含)、JsonInclude.Include.NON_EMPTY(值不为空时包含)和 JsonInclude.Include.CUSTOM(自定义条件)。

content:用于指定自定义条件的实现类。

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Person {
    private String fullName;
    private Integer age;
    // getters and setters
}
Person person = new Person();
person.setFullName("John Smith");
// person.setAge(null);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(person);
// {"fullName":"John Smith"}
Person person2 = mapper.readValue("{\"fullName\":\"John Smith\",\"age\":null}", Person.class);
System.out.println(person2.getFullName());
// John Smith
System.out.println(person2.getAge());
// null

@JsonCreator 注解:

该注解用于指定反序列化时使用的构造方法或工厂方法,常用的参数有:

无参数。

public class Person {
    private String fullName;
    private Integer age;
    @JsonCreator
    public Person(@JsonProperty("fullName") String fullName, @JsonProperty("age") Integer age) {
        this.fullName = fullName;
        this.age = age;
    }
    // getters and setters
}
ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue("{\"fullName\":\"John Smith\",\"age\":30}", Person.class);
System.out.println(person.getFullName());
// John Smith
System.out.println(person.getAge());
// 30

@JsonSetter 注解:

该注解用于指定反序列化时使用的方法,常用的参数有:

value:用于指定 JSON 属性的名称,当方法名和 JSON 属性名称不一致时使用。

public class Person {
    private String fullName;
    private Integer age;
    @JsonSetter("name")
    public void setFullName(String fullName) {
        this.fullName = fullName;
    }
    // getters and setters
}
ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue("{\"name\":\"John Smith\",\"age\":30}", Person.class);
System.out.println(person.getFullName());
// John Smith
System.out.println(person.getAge());
// 30

@JsonGetter 注解:

该注解用于指定序列化时使用的方法,常用的参数有:

value:用于指定 JSON 属性的名称,当方法名和 JSON 属性名称不一致时使用。

public class Person {
    private String fullName;
    private Integer age;
    @JsonGetter("name")
    public String getFullName() {
        return fullName;
    }
    // getters and setters
}

@JsonAnySetter 注解:

该注解用于指定反序列化时使用的方法,用于处理 JSON 中未知的属性,常用的参数有:

无参数。

public class Person {
    private String fullName;
    private Map<String, Object> otherProperties = new HashMap<>();
    @JsonAnySetter
    public void setOtherProperties(String key, Object value) {
        otherProperties.put(key, value);
    }
    // getters and setters
}
ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue("{\"fullName\":\"John Smith\",\"age\":30}", Person.class);
System.out.println(person.getFullName());
// John Smith
System.out.println(person.getOtherProperties());
// {age=30}

@JsonAnyGetter 注解:

该注解用于指定序列化时使用的方法,用于处理 Java 对象中未知的属性,常用的参数有:

无参数。

public class Person {
    private String fullName;
    private Map<String, Object> otherProperties = new HashMap<>();
    public void addOtherProperty(String key, Object value) {
        otherProperties.put(key, value);
    }
    @JsonAnyGetter
    public Map<String, Object> getOtherProperties() {
        return otherProperties;
    }
    // getters and setters
}
Person person = new Person();
person.setFullName("John Smith");
person.addOtherProperty("age", 30);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(person);
// {"fullName":"John Smith","age":30}

@JsonTypeInfo 注解:

该注解用于指定 Java 对象在序列化和反序列化时的类型信息,常用的参数有:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Rectangle.class, name = "rectangle"),
    @JsonSubTypes.Type(value = Circle.class, name = "circle")
})
public abstract class Shape {
    // ...
}
public class Rectangle extends Shape {
    // ...
}
public class Circle extends Shape {
    // ...
}
Shape shape = new Rectangle();
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(shape);
// {"type":"rectangle"}
Shape shape2 = mapper.readValue(json, Shape.class);
System.out.println(shape2.getClass().getSimpleName());
// Rectangle

自定义序列化和反序列化

你可以创建自定义序列化器和反序列化器以自定义特定字段或类的序列化和反序列化行为。为此,请创建一个实现JsonSerializerJsonDeserializer接口的类,并在需要自定义的字段或类上使用@JsonSerialize@JsonDeserialize注解。例如:

public class CustomDateSerializer extends JsonSerializer<Date> {
    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    @Override
    public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString(dateFormat.format(value));
    }
}
public class Person {
    private String name;
    @JsonSerialize(using = CustomDateSerializer.class)
    private Date birthdate;
    // ...其他代码...
}

使用JsonNode进行动态解析

你可以使用JsonNode类来动态地解析和操作JSON数据。例如:

String jsonString = "{\"name\":\"Alice\",\"age\":30,\"address\":{\"street\":\"Main St\",\"city\":\"New York\"}}";
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(jsonString);
String name = rootNode.get("name").asText(); // Alice
int age = rootNode.get("age").asInt(); // 30
String street = rootNode.get("address").get("street").asText(); // Main St

处理日期和时间类型

Jackson可以处理Java日期和时间类型,例如java.util.Date和Java 8时间库中的类型。你可以通过配置ObjectMapper来指定日期和时间格式,例如:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));

处理泛型

Jackson可以处理泛型类型,例如List<T>Map<String, T>。在反序列化时,你需要使用TypeReference来指定泛型类型。例如:

String jsonString = "[{\"name\":\"Alice\",\"age\":30},{\"name\":\"Bob\",\"age\":25}]";
ObjectMapper objectMapper = new ObjectMapper();
List<Person> persons = objectMapper.readValue(jsonString, new TypeReference<List<Person>>() {});

使用模块扩展Jackson(如Java 8时间支持)

Jackson可以通过模块来扩展其功能。例如,你可以使用jackson-datatype-jsr310模块为Jackson添加对Java 8时间库的支持。首先,将依赖添加到项目中:

Maven

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.13.0</version>
</dependency>

Gradle

dependencies {
    implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.0'
}

然后,你需要注册模块到ObjectMapper

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());

现在,Jackson可以正确地处理Java 8时间库中的类型,例如LocalDateLocalTimeInstant

总结

Jackson的优势和局限性

优势

局限性

建议和最佳实践

其他的JSON库

除了Jackson之外,还有其他一些流行的Java JSON处理库。以下是一些常见的库:

这些库各有优缺点,选择哪个库取决于项目的具体需求和团队的熟悉程度。在实际项目中,你可能需要比较这些库的性能、功能、易用性等方面的差异,以找到最适合你的解决方案。

以上就是从Java到JSON一起探索Jackson的魔力的详细内容,更多关于Java Jackson的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文