引言
Jackson简介
Jackson是一个用于处理JSON数据的开源Java库。JSON(JavaScript Object Notation)是一种轻量级的数据交换格局,易于阅读和编写,一起也易于计算机解析和生成。在Java领域,Jackson已经成为处理JSON数据的事实标准库。它供给了丰厚的功用,包括将Java目标转化为JSON字符串(序列化)以及将JSON字符串转化为Java目标(反序列化)。
Jackson首要由三个中心包组成:
- jackson-databind:供给了通用的数据绑定功用(将Java目标与JSON数据彼此转化)
- jackson-core:供给了中心的初级JSON处理API(例如JsonParser和JsonGenerator)
- jackson-annotations:供给了用于装备数据绑定的注解
为什么选择Jackson
尽管Java生态系统中有其他处理JSON数据的库(如Gson和JSON-java),但Jackson仍然是许多开发者的首选,原因包括:
- 功用:Jackson功用优越,对内存和CPU的运用都相对较低。许多功用基准测验表明,Jackson在序列化和反序列化方面都比其他库更快。
- 功用丰厚:Jackson供给了许多功用,包括注解、自定义序列化和反序列化、动态解析等,使其十分灵活和强壮。
- 易于运用:Jackson的API简略易用,使得开发者能够轻松地在他们的应用程序中集成和运用。
- 社区支撑:Jackson拥有庞大的开发者社区,这意味着有更多的文档、教程和问题解答可供参考。
- 模块化:Jackson支撑经过模块扩展其功用,例如Java 8时刻库、Joda-Time和Kotlin等。
- 兼容性:Jackson能够很好地与其他流行的Java框架(如Spring)集成。
综上所述,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和组件:
-
ObjectMapper:这是Jackson库的中心类,用于序列化和反序列化操作。首要办法有:
-
writeValueAsString(Object)
:将Java目标序列化为JSON字符串。 -
readValue(String, Class)
:将JSON字符串反序列化为Java目标。
-
-
JsonParser:用于从JSON数据源(如文件、输入流或字符串)解析JSON数据。首要办法有:
-
nextToken()
:获取下一个JSON令牌(如START_OBJECT、FIELD_NAME等)。 -
getValueAsString()
:将当时令牌作为字符串回来。 -
getValueAsInt()
:将当时令牌作为整数回来。
-
-
JsonGenerator:用于将JSON数据写入数据源(如文件、输出流或字符串缓冲区)。首要办法有:
-
writeStartObject()
:写入开端目标符号({
)。 -
writeFieldName(String)
:写入字段称号。 -
writeString(String)
:写入字符串值。 -
writeEndObject()
:写入结束目标符号(}
)。
-
-
JsonNode:用于表明JSON树模型中的节点,能够是目标、数组、字符串、数字等。首要办法有:
-
get(String)
:获取指定字段的子节点。 -
path(String)
:获取指定字段的子节点,假如不存在则回来一个“missing”节点。 -
isObject()
:查看当时节点是否是一个目标。 -
isArray()
:查看当时节点是否是一个数组。
-
-
注解:Jackson供给了一系列注解来装备序列化和反序列化进程。一些常用注解包括:
-
@JsonProperty
:指定字段在JSON数据中的称号。 -
@JsonIgnore
:指定字段在序列化和反序列化进程中被忽略。 -
@JsonCreator
:指定用于反序列化的结构函数或工厂办法。 -
@JsonSerialize
:指定用于序列化特定字段或类的自定义序列化器。 -
@JsonDeserialize
:指定用于反序列化特定字段或类的自定义反序列化器。
-
这只是Jackson库API和组件的一个概览。假如你想深化了解详细的API和运用办法,请参考官方文档(github.com/FasterXML/j… )和相关教程。一起,实践编程进程中,依据详细需求学习和了解相应的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 目标在序列化和反序列化时的类型信息,常用的参数有:
-
use
:用于指定类型信息的运用方法,可选的取值有JsonTypeInfo.Id.CLASS
(运用 Java 类的全限定名)、JsonTypeInfo.Id.NAME
(运用称号)和JsonTypeInfo.Id.NONE
(不运用类型信息)。 -
include
:用于指定类型信息的包括方法,可选的取值有JsonTypeInfo.As.PROPERTY
(作为 JSON 特点)和JsonTypeInfo.As.EXTERNAL_PROPERTY
(作为外部特点)。 -
property
:用于指定包括类型信息的特点名,当include
的值为JsonTypeInfo.As.PROPERTY
时运用。 -
visible
:用于指定类型信息是否可见。
@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
-
自定义序列化和反序列化
你能够创立自定义序列化器和反序列化器以自定义特定字段或类的序列化和反序列化行为。为此,请创立一个完成JsonSerializer
或JsonDeserializer
接口的类,并在需求自定义的字段或类上运用@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时刻库中的类型,例如LocalDate
、LocalTime
和Instant
。
总结
Jackson的优势和局限性
优势:
- 功用优异:Jackson在序列化和反序列化进程中表现出优异的功用,通常比其他Java JSON库更快。
- 灵活性:经过注解、自定义序列化器/反序列化器等功用,Jackson供给了丰厚的装备选项,答应你依据需求灵活地处理JSON数据。
- 易于运用:Jackson的API设计简练明了,易于学习和运用。一起,官方文档和社区支撑也十分丰厚。
- 可扩展性:经过模块系统,你能够轻松地为Jackson增加新功用或与其他库进行集成。
局限性:
- 库大小:因为Jackson供给了许多功用和选项,它的库文件相对较大。在某些对程序大小有严格要求的场景中,这或许是一个问题。
- 学习曲线:虽然Jackson的根本功用易于学习,但要充分利用其高档特性,或许需求必定的学习成本。
建议和最佳实践
- 了解你的需求:在运用Jackson之前,请确保你了解项目的需求。针对详细需求,学习和运用相应的API和特性会愈加高效。
- 遵从Java命名标准:运用标准的Java命名标准(如驼峰命名法)来命名字段和类。这将有助于Jackson自动处理JSON字段映射。
-
尽量防止循环引证:在Java目标模型中防止循环引证,因为这或许导致序列化进程中出现问题。假如的确存在循环引证,请运用
@JsonManagedReference
和@JsonBackReference
注解来解决。 - 运用注解进行装备:在或许的情况下,运用注解来装备序列化和反序列化进程。这将使装备愈加集中和易于理解。
- 优先运用目标模型:尽量运用Java目标模型来表明JSON数据,而非动态解析。这将使代码愈加清晰和易于维护。
其他的JSON库
除了Jackson之外,还有其他一些流行的Java JSON处理库。以下是一些常见的库:
-
Gson:Gson是Google开发的一个Java库,用于将Java目标转化为JSON表明以及将JSON字符串转化为等效的Java目标。Gson的API简练易用,功用也适当不错。官方网站:github.com/google/gson
-
Fastjson:Fastjson是Alibaba开发的一个高功用的JSON库。Fastjson供给了灵活的API和丰厚的功用,一起注重功用优化。但是,它在安全性方面存在一些问题,因此在运用时需求谨慎。官方网站:github.com/alibaba/fas…
-
JSON-java(org.json):JSON-java库,也称为org.json库,是一个十分轻量级的JSON处理库。它供给了根本的JSON编码和解码功用,但不支撑目标映射等高档功用。官方网站:github.com/stleary/JSO…
-
Moshi:Moshi是Square公司开发的一个现代化的JSON库,具有简略易用的API和杰出的功用。Moshi支撑Kotlin协程,并与Kotlin编程言语十分兼容。官方网站:github.com/square/mosh…
-
Boon:Boon是另一个高功用的JSON处理库。它具有易用的API,支撑流式处理和速度优化。但是,Boon的社区和文档相对较少。官方网站:github.com/boonproject…
这些库各有优缺点,选择哪个库取决于项目的详细需求和团队的熟悉程度。在实践项目中,你或许需求比较这些库的功用、功用、易用性等方面的差异,以找到最适合你的解决方案。