Jackson JSON Java Parser API 示例教程
Jackson JSON Java Parser非常流行,在 Spring 框架中也有使用。Java JSON 处理 API不太用户友好,不提供从 Json 自动转换为 Java 对象和反之亦然的功能。幸运的是,我们有一些可用于 JSON 处理的替代 API。在上一篇文章中,我们了解了Google Gson API,并了解了它是多么容易使用。
Jackson JSON Java 解析器
为了在我们的项目中使用 Jackson JSON Java API,我们可以将其添加到项目构建路径中,或者如果您使用 maven,我们可以添加以下依赖项。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
</dependency>
jackson-databind jar 依赖于jackson-core和jackson-annotations库,因此如果您将它们直接添加到构建路径,请确保添加所有三个,否则您将收到运行时错误。Jackson JSON Parser API 提供了将 JSON 转换为 POJO 对象的简便方法,并支持从 JSON 数据轻松转换为 Map。Jackson 也支持泛型并直接将它们从 JSON 转换为对象。
Jackson JSON 示例
对于 JSON 到 POJO/Java 对象转换的示例,我们将采用一个包含嵌套对象和数组的复杂示例。我们将使用 Java 对象中的数组、列表和 Map 进行转换。我们的复杂 json 存储在文件 employee.txt 中,结构如下:
{
"id": 123,
"name": "Pankaj",
"permanent": true,
"address": {
"street": "Albany Dr",
"city": "San Jose",
"zipcode": 95129
},
"phoneNumbers": [
123456,
987654
],
"role": "Manager",
"cities": [
"Los Angeles",
"New York"
],
"properties": {
"age": "29 years",
"salary": "1000 USD"
}
}
我们有以下与 json 数据相对应的 java 类。
package com.journaldev.jackson.model;
public class Address {
private String street;
private String city;
private int zipcode;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getZipcode() {
return zipcode;
}
public void setZipcode(int zipcode) {
this.zipcode = zipcode;
}
@Override
public String toString(){
return getStreet() + ", "+getCity()+", "+getZipcode();
}
}
地址类对应于根 json 数据中的内部对象。
package com.journaldev.jackson.model;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class Employee {
private int id;
private String name;
private boolean permanent;
private Address address;
private long[] phoneNumbers;
private String role;
private List<String> cities;
private Map<String, String> properties;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isPermanent() {
return permanent;
}
public void setPermanent(boolean permanent) {
this.permanent = permanent;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public long[] getPhoneNumbers() {
return phoneNumbers;
}
public void setPhoneNumbers(long[] phoneNumbers) {
this.phoneNumbers = phoneNumbers;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("***** Employee Details *****\n");
sb.append("ID="+getId()+"\n");
sb.append("Name="+getName()+"\n");
sb.append("Permanent="+isPermanent()+"\n");
sb.append("Role="+getRole()+"\n");
sb.append("Phone Numbers="+Arrays.toString(getPhoneNumbers())+"\n");
sb.append("Address="+getAddress()+"\n");
sb.append("Cities="+Arrays.toString(getCities().toArray())+"\n");
sb.append("Properties="+getProperties()+"\n");
sb.append("*****************************");
return sb.toString();
}
public List<String> getCities() {
return cities;
}
public void setCities(List<String> cities) {
this.cities = cities;
}
public Map<String, String> getProperties() {
return properties;
}
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
}
Employee 是代表根 json 对象的 java bean。现在让我们看看如何使用 Jackson JSON 解析器 API 将 JSON 转换为 java 对象。
package com.journaldev.jackson.json;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.journaldev.jackson.model.Address;
import com.journaldev.jackson.model.Employee;
public class JacksonObjectMapperExample {
public static void main(String[] args) throws IOException {
//read json file data to String
byte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));
//create ObjectMapper instance
ObjectMapper objectMapper = new ObjectMapper();
//convert json string to object
Employee emp = objectMapper.readValue(jsonData, Employee.class);
System.out.println("Employee Object\n"+emp);
//convert Object to json string
Employee emp1 = createEmployee();
//configure Object mapper for pretty print
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
//writing to console, can write to any output stream such as file
StringWriter stringEmp = new StringWriter();
objectMapper.writeValue(stringEmp, emp1);
System.out.println("Employee JSON is\n"+stringEmp);
}
public static Employee createEmployee() {
Employee emp = new Employee();
emp.setId(100);
emp.setName("David");
emp.setPermanent(false);
emp.setPhoneNumbers(new long[] { 123456, 987654 });
emp.setRole("Manager");
Address add = new Address();
add.setCity("Bangalore");
add.setStreet("BTM 1st Stage");
add.setZipcode(560100);
emp.setAddress(add);
List<String> cities = new ArrayList<String>();
cities.add("Los Angeles");
cities.add("New York");
emp.setCities(cities);
Map<String, String> props = new HashMap<String, String>();
props.put("salary", "1000 Rs");
props.put("age", "28 years");
emp.setProperties(props);
return emp;
}
}
当我们运行上述程序时,您将得到以下输出。
Employee Object
***** Employee Details *****
ID=123
Name=Pankaj
Permanent=true
Role=Manager
Phone Numbers=[123456, 987654]
Address=Albany Dr, San Jose, 95129
Cities=[Los Angeles, New York]
Properties={age=29 years, salary=1000 USD}
*****************************
Employee JSON is
//printing same as above json file data
com.fasterxml.jackson.databind.ObjectMapper是 Jackson API 中最重要的类,它提供 readValue() 和 writeValue() 方法将 JSON 转换为Java 对象,将Java 对象转换为 JSON。ObjectMapper类可以重用,我们可以将其初始化一次作为 Singleton 对象。readValue() 和 writeValue() 方法有许多重载版本,可用于处理字节数组、文件、输入/输出流和 Reader/Writer 对象。
Jackson JSON - 将 JSON 转换为 Map
有时我们在 data.txt 文件中有一个如下所示的 JSON 对象:
{
"name": "David",
"role": "Manager",
"city": "Los Angeles"
}
我们希望将其转换为 Map,而不是具有相同属性和键的 Java 对象。我们可以使用以下代码中的两种方法在 Jackson JSON API 中轻松完成此操作:
//converting json to Map
byte[] mapData = Files.readAllBytes(Paths.get("data.txt"));
Map<String,String> myMap = new HashMap<String, String>();
ObjectMapper objectMapper = new ObjectMapper();
myMap = objectMapper.readValue(mapData, HashMap.class);
System.out.println("Map is: "+myMap);
//another way
myMap = objectMapper.readValue(mapData, new TypeReference<HashMap<String,String>>() {});
System.out.println("Map using TypeReference: "+myMap);
一旦我们执行上述代码片段,我们会得到以下输出:
Map is: {name=David, role=Manager, city=Los Angeles}
Map using TypeReference: {name=David, role=Manager, city=Los Angeles}
Jackson JSON - 读取特定的 JSON 键
有时我们有 json 数据,但我们只对其中的几个键值感兴趣,因此在这种情况下将整个 JSON 转换为对象并不是一个好主意。Jackson JSON API 提供了将 json 数据读取为树(如DOM Parser)的选项,我们可以通过它读取 JSON 对象的特定元素。下面的代码提供了从 json 文件读取特定条目的代码片段。
//read json file data to String
byte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));
//create ObjectMapper instance
ObjectMapper objectMapper = new ObjectMapper();
//read JSON like DOM Parser
JsonNode rootNode = objectMapper.readTree(jsonData);
JsonNode idNode = rootNode.path("id");
System.out.println("id = "+idNode.asInt());
JsonNode phoneNosNode = rootNode.path("phoneNumbers");
Iterator<JsonNode> elements = phoneNosNode.elements();
while(elements.hasNext()){
JsonNode phone = elements.next();
System.out.println("Phone No = "+phone.asLong());
}
当我们执行上述代码片段时,我们得到以下输出。
id = 123
Phone No = 123456
Phone No = 987654
Jackson JSON - 编辑 JSON 文档
Jackson JSON Java API 提供了有用的方法来添加、编辑和删除 JSON 数据中的键,然后我们可以将其保存为新的 json 文件或将其写入任何流。下面的代码向我们展示了如何轻松地做到这一点。
byte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));
ObjectMapper objectMapper = new ObjectMapper();
//create JsonNode
JsonNode rootNode = objectMapper.readTree(jsonData);
//update JSON data
((ObjectNode) rootNode).put("id", 500);
//add new key value
((ObjectNode) rootNode).put("test", "test value");
//remove existing key
((ObjectNode) rootNode).remove("role");
((ObjectNode) rootNode).remove("properties");
objectMapper.writeValue(new File("updated_emp.txt"), rootNode);
如果您执行上述代码并查找新文件,您会注意到它没有“role”和“properties”键。您还会注意到“id”值已更新为 500,并且新键“test”已添加到 updated_emp.txt 文件中。
Jackson JSON 流 API 示例
Jackson JSON Java API 还提供流式支持,这有助于处理大型 json 数据,因为它将整个文件读取为标记并使用更少的内存。流式 API 的唯一问题是我们需要在解析 JSON 数据时处理所有标记。如果我们将 json 数据作为 {“role”:“Manager”},那么我们将按顺序获得以下标记 - {(起始对象)、“role”(键名)、“Manager”(键值)和 }(结束对象)。冒号 (:) 是 JSON 中的分隔符,因此不被视为标记。
package com.journaldev.jackson.json;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.journaldev.jackson.model.Address;
import com.journaldev.jackson.model.Employee;
public class JacksonStreamingReadExample {
public static void main(String[] args) throws JsonParseException, IOException {
//create JsonParser object
JsonParser jsonParser = new JsonFactory().createParser(new File("employee.txt"));
//loop through the tokens
Employee emp = new Employee();
Address address = new Address();
emp.setAddress(address);
emp.setCities(new ArrayList<String>());
emp.setProperties(new HashMap<String, String>());
List<Long> phoneNums = new ArrayList<Long>();
boolean insidePropertiesObj=false;
parseJSON(jsonParser, emp, phoneNums, insidePropertiesObj);
long[] nums = new long[phoneNums.size()];
int index = 0;
for(Long l :phoneNums){
nums[index++] = l;
}
emp.setPhoneNumbers(nums);
jsonParser.close();
//print employee object
System.out.println("Employee Object\n\n"+emp);
}
private static void parseJSON(JsonParser jsonParser, Employee emp,
List<Long> phoneNums, boolean insidePropertiesObj) throws JsonParseException, IOException {
//loop through the JsonTokens
while(jsonParser.nextToken() != JsonToken.END_OBJECT){
String name = jsonParser.getCurrentName();
if("id".equals(name)){
jsonParser.nextToken();
emp.setId(jsonParser.getIntValue());
}else if("name".equals(name)){
jsonParser.nextToken();
emp.setName(jsonParser.getText());
}else if("permanent".equals(name)){
jsonParser.nextToken();
emp.setPermanent(jsonParser.getBooleanValue());
}else if("address".equals(name)){
jsonParser.nextToken();
//nested object, recursive call
parseJSON(jsonParser, emp, phoneNums, insidePropertiesObj);
}else if("street".equals(name)){
jsonParser.nextToken();
emp.getAddress().setStreet(jsonParser.getText());
}else if("city".equals(name)){
jsonParser.nextToken();
emp.getAddress().setCity(jsonParser.getText());
}else if("zipcode".equals(name)){
jsonParser.nextToken();
emp.getAddress().setZipcode(jsonParser.getIntValue());
}else if("phoneNumbers".equals(name)){
jsonParser.nextToken();
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
phoneNums.add(jsonParser.getLongValue());
}
}else if("role".equals(name)){
jsonParser.nextToken();
emp.setRole(jsonParser.getText());
}else if("cities".equals(name)){
jsonParser.nextToken();
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
emp.getCities().add(jsonParser.getText());
}
}else if("properties".equals(name)){
jsonParser.nextToken();
while(jsonParser.nextToken() != JsonToken.END_OBJECT){
String key = jsonParser.getCurrentName();
jsonParser.nextToken();
String value = jsonParser.getText();
emp.getProperties().put(key, value);
}
}
}
}
}
JsonParser是用于读取 json 数据的 jackson json 流式 API,我们使用它从文件中读取数据,然后使用 parseJSON() 方法循环遍历标记并处理它们以创建我们的 java 对象。请注意,parseJSON() 方法对“address”进行递归调用,因为它是 json 数据中的嵌套对象。对于解析数组,我们循环遍历 json 文档。我们可以使用JsonGenerator类通过流式 API 生成 json 数据。
package com.journaldev.jackson.json;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Set;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.journaldev.jackson.model.Employee;
public class JacksonStreamingWriteExample {
public static void main(String[] args) throws IOException {
Employee emp = JacksonObjectMapperExample.createEmployee();
JsonGenerator jsonGenerator = new JsonFactory()
.createGenerator(new FileOutputStream("stream_emp.txt"));
//for pretty printing
jsonGenerator.setPrettyPrinter(new DefaultPrettyPrinter());
jsonGenerator.writeStartObject(); // start root object
jsonGenerator.writeNumberField("id", emp.getId());
jsonGenerator.writeStringField("name", emp.getName());
jsonGenerator.writeBooleanField("permanent", emp.isPermanent());
jsonGenerator.writeObjectFieldStart("address"); //start address object
jsonGenerator.writeStringField("street", emp.getAddress().getStreet());
jsonGenerator.writeStringField("city", emp.getAddress().getCity());
jsonGenerator.writeNumberField("zipcode", emp.getAddress().getZipcode());
jsonGenerator.writeEndObject(); //end address object
jsonGenerator.writeArrayFieldStart("phoneNumbers");
for(long num : emp.getPhoneNumbers())
jsonGenerator.writeNumber(num);
jsonGenerator.writeEndArray();
jsonGenerator.writeStringField("role", emp.getRole());
jsonGenerator.writeArrayFieldStart("cities"); //start cities array
for(String city : emp.getCities())
jsonGenerator.writeString(city);
jsonGenerator.writeEndArray(); //closing cities array
jsonGenerator.writeObjectFieldStart("properties");
Set<String> keySet = emp.getProperties().keySet();
for(String key : keySet){
String value = emp.getProperties().get(key);
jsonGenerator.writeStringField(key, value);
}
jsonGenerator.writeEndObject(); //closing properties
jsonGenerator.writeEndObject(); //closing root object
jsonGenerator.flush();
jsonGenerator.close();
}
}
与 JsonParser 相比,JsonGenerator 更易于使用。以上就是 Jackson JSON Parser Java API 的快速参考教程。Jackson JSON Java API 易于使用,并为开发人员处理 JSON 数据提供了许多选项。从以下链接下载项目并试用它以探索有关 Jackson Json API 的更多选项。
下载 Jackson JSON 项目