Java JSON 示例
欢迎来到 Java JSON 示例教程。JSON (JavaScript 对象表示法)是一种基于文本的轻量级技术,用于生成人类可读的格式化数据。JSON 以键值对的形式表示对象数据。我们也可以嵌套 JSON 对象,它也提供了一种表示数组的简单方法。
Java JSON
JSON 被广泛用于 Web 应用程序或服务器响应,因为它比 XML 更轻量且更紧凑。JSON 对象易于读写,并且大多数技术都提供对 JSON 对象的支持。这就是 Java Web 服务中的 JSON 非常流行的原因。JSR353最终成为Java EE 7,它是 Java JSON 处理 API。jsonp是 Java JSON 处理 API 的参考实现。我们可以通过添加以下依赖项在 maven 项目中使用它。
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.2</version>
</dependency>
如果您使用的是 GlassFish 4.0,那么您可以保留提供的范围,因为它已经包含在服务器中。JSON API 提供了两种 JSON 处理方式:
- 对象模型 API - 它类似于DOM 解析器,适用于小对象。
- 流式 API - 它类似于StaX Parser,适用于您不想将整个对象保存在内存中的大型对象。
Java JSON API的一些重要接口是:
- javax.json.JsonReader:我们可以使用它来读取 JSON 对象或数组到 JsonObject。我们可以从 Json 类或 JsonReaderFactory 获取 JsonReader。
- javax.json.JsonWriter:我们可以用它将 JSON 对象写入输出流。
- javax.json.stream.JsonParser:它作为拉解析器工作并为读取 JSON 对象提供流支持。
- javax.json.stream.JsonGenerator:我们可以使用它以流式方式将 JSON 对象写入输出源。
- javax.json.Json:这是用于创建 JSON 处理对象的工厂类。此类提供了创建这些对象及其相应工厂的最常用方法。工厂类提供了创建这些对象的各种方法。
- javax.json.JsonObject:JsonObject 表示不可变的 JSON 对象值。
让我们通过简单的程序来研究 Java JSON API 的用法,我们在文件 employee.txt 中存储了一个 JSON 对象;
{
"id":123,
"name":"Pankaj Kumar",
"permanent":true,
"address":{
"street":"El Camino Real",
"city":"San Jose",
"zipcode":95014
},
"phoneNumbers":[9988664422, 1234567890],
"role":"Developer"
}
我们有表示上述 JSON 格式的 Java bean 类:
package com.journaldev.model;
import java.util.Arrays;
public class Employee {
private int id;
private String name;
private boolean permanent;
private Address address;
private long[] phoneNumbers;
private String role;
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());
sb.append("\n*****************************");
return sb.toString();
}
}
package com.journaldev.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();
}
}
我已经重写了 toString() 方法来返回我们将在 JSON 实现类中使用的人类可读的字符串表示形式。
Java JSON 读取示例
package com.journaldev.json;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;
import com.journaldev.model.Address;
import com.journaldev.model.Employee;
public class EmployeeJSONReader {
public static final String JSON_FILE="employee.txt";
public static void main(String[] args) throws IOException {
InputStream fis = new FileInputStream(JSON_FILE);
//create JsonReader object
JsonReader jsonReader = Json.createReader(fis);
/**
* We can create JsonReader from Factory also
JsonReaderFactory factory = Json.createReaderFactory(null);
jsonReader = factory.createReader(fis);
*/
//get JsonObject from JsonReader
JsonObject jsonObject = jsonReader.readObject();
//we can close IO resource and JsonReader now
jsonReader.close();
fis.close();
//Retrieve data from JsonObject and create Employee bean
Employee emp = new Employee();
emp.setId(jsonObject.getInt("id"));
emp.setName(jsonObject.getString("name"));
emp.setPermanent(jsonObject.getBoolean("permanent"));
emp.setRole(jsonObject.getString("role"));
//reading arrays from json
JsonArray jsonArray = jsonObject.getJsonArray("phoneNumbers");
long[] numbers = new long[jsonArray.size()];
int index = 0;
for(JsonValue value : jsonArray){
numbers[index++] = Long.parseLong(value.toString());
}
emp.setPhoneNumbers(numbers);
//reading inner object from json object
JsonObject innerJsonObject = jsonObject.getJsonObject("address");
Address address = new Address();
address.setStreet(innerJsonObject.getString("street"));
address.setCity(innerJsonObject.getString("city"));
address.setZipcode(innerJsonObject.getInt("zipcode"));
emp.setAddress(address);
//print employee bean information
System.out.println(emp);
}
}
实现很简单,感觉就像从 HashMap 获取参数一样。JsonReaderFactory 实现了工厂设计模式。一旦我们执行上述程序,我们就会得到以下输出。
***** Employee Details *****
ID=123
Name=Pankaj Kumar
Permanent=true
Role=Developer
Phone Numbers=[9988664422, 1234567890]
Address=El Camino Real, San Jose, 95014
*****************************
Java JSON 写入示例
package com.journaldev.json;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonWriter;
import com.journaldev.model.Address;
import com.journaldev.model.Employee;
public class EmployeeJSONWriter {
public static void main(String[] args) throws FileNotFoundException {
Employee emp = createEmployee();
JsonObjectBuilder empBuilder = Json.createObjectBuilder();
JsonObjectBuilder addressBuilder = Json.createObjectBuilder();
JsonArrayBuilder phoneNumBuilder = Json.createArrayBuilder();
for (long phone : emp.getPhoneNumbers()) {
phoneNumBuilder.add(phone);
}
addressBuilder.add("street", emp.getAddress().getStreet())
.add("city", emp.getAddress().getCity())
.add("zipcode", emp.getAddress().getZipcode());
empBuilder.add("id", emp.getId())
.add("name", emp.getName())
.add("permanent", emp.isPermanent())
.add("role", emp.getRole());
empBuilder.add("phoneNumbers", phoneNumBuilder);
empBuilder.add("address", addressBuilder);
JsonObject empJsonObject = empBuilder.build();
System.out.println("Employee JSON String\n"+empJsonObject);
//write to file
OutputStream os = new FileOutputStream("emp.txt");
JsonWriter jsonWriter = Json.createWriter(os);
/**
* We can get JsonWriter from JsonWriterFactory also
JsonWriterFactory factory = Json.createWriterFactory(null);
jsonWriter = factory.createWriter(os);
*/
jsonWriter.writeObject(empJsonObject);
jsonWriter.close();
}
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);
return emp;
}
}
一旦我们运行上述应用程序,我们就会得到以下响应:
Employee JSON String
{"id":100,"name":"David","permanent":false,"role":"Manager","phoneNumbers":[123456,987654],"address":{"street":"BTM 1st Stage","city":"Bangalore","zipcode":560100}}
JSON 对象也保存在 emp.txt 文件中。JsonObjectBuilder 实现了构建器模式,使其非常易于使用。
Java JSON 解析器示例
Java JsonParser 是一个拉式解析器,我们使用next()方法读取下一个元素,该方法返回一个 Event 对象。javax.json.stream.JsonParser.Event
是一个枚举,使其类型安全且易于使用。我们可以在switch case中使用它来设置我们的 java bean 属性。
package com.journaldev.json;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.json.Json;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.journaldev.model.Address;
import com.journaldev.model.Employee;
public class EmployeeJSONParser {
public static final String FILE_NAME = "employee.txt";
public static void main(String[] args) throws IOException {
InputStream fis = new FileInputStream(FILE_NAME);
JsonParser jsonParser = Json.createParser(fis);
/**
* We can create JsonParser from JsonParserFactory also with below code
* JsonParserFactory factory = Json.createParserFactory(null);
* jsonParser = factory.createParser(fis);
*/
Employee emp = new Employee();
Address address = new Address();
String keyName = null;
List<Long> phoneNums = new ArrayList<Long>();
while (jsonParser.hasNext()) {
Event event = jsonParser.next();
switch (event) {
case KEY_NAME:
keyName = jsonParser.getString();
break;
case VALUE_STRING:
setStringValues(emp, address, keyName, jsonParser.getString());
break;
case VALUE_NUMBER:
setNumberValues(emp, address, keyName, jsonParser.getLong(), phoneNums);
break;
case VALUE_FALSE:
setBooleanValues(emp, address, keyName, false);
break;
case VALUE_TRUE:
setBooleanValues(emp, address, keyName, true);
break;
case VALUE_NULL:
// don't set anything
break;
default:
// we are not looking for other events
}
}
emp.setAddress(address);
long[] nums = new long[phoneNums.size()];
int index = 0;
for(Long l :phoneNums){
nums[index++] = l;
}
emp.setPhoneNumbers(nums);
System.out.println(emp);
//close resources
fis.close();
jsonParser.close();
}
private static void setNumberValues(Employee emp, Address address,
String keyName, long value, List<Long> phoneNums) {
switch(keyName){
case "zipcode":
address.setZipcode((int)value);
break;
case "id":
emp.setId((int) value);
break;
case "phoneNumbers":
phoneNums.add(value);
break;
default:
System.out.println("Unknown element with key="+keyName);
}
}
private static void setBooleanValues(Employee emp, Address address,
String key, boolean value) {
if("permanent".equals(key)){
emp.setPermanent(value);
}else{
System.out.println("Unknown element with key="+key);
}
}
private static void setStringValues(Employee emp, Address address,
String key, String value) {
switch(key){
case "name":
emp.setName(value);
break;
case "role":
emp.setRole(value);
break;
case "city":
address.setCity(value);
break;
case "street":
address.setStreet(value);
break;
default:
System.out.println("Unknown Key="+key);
}
}
}
最大的复杂性来自于我们需要编写逻辑来解析数据,有时它会变得很复杂。由于我们读取的是与 JsonReader 相同的文件,因此输出与 EmployeeJsonReader 程序相同。
Java JsonGenerator 示例
package com.journaldev.json;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.json.Json;
import javax.json.stream.JsonGenerator;
import com.journaldev.model.Employee;
public class EmployeeJSONGenerator {
public static void main(String[] args) throws IOException {
OutputStream fos = new FileOutputStream("emp_stream.txt");
JsonGenerator jsonGenerator = Json.createGenerator(fos);
/**
* We can get JsonGenerator from Factory class also
* JsonGeneratorFactory factory = Json.createGeneratorFactory(null);
* jsonGenerator = factory.createGenerator(fos);
*/
Employee emp = EmployeeJSONWriter.createEmployee();
jsonGenerator.writeStartObject(); // {
jsonGenerator.write("id", emp.getId()); // "id":123
jsonGenerator.write("name", emp.getName());
jsonGenerator.write("role", emp.getRole());
jsonGenerator.write("permanent", emp.isPermanent());
jsonGenerator.writeStartObject("address") //start of address object
.write("street", emp.getAddress().getStreet())
.write("city",emp.getAddress().getCity())
.write("zipcode",emp.getAddress().getZipcode())
.writeEnd(); //end of address object
jsonGenerator.writeStartArray("phoneNumbers"); //start of phone num array
for(long num : emp.getPhoneNumbers()){
jsonGenerator.write(num);
}
jsonGenerator.writeEnd(); // end of phone num array
jsonGenerator.writeEnd(); // }
jsonGenerator.close();
}
}
JsonGenerator 非常易于使用,并且为大数据提供了良好的性能。这就是 Java JSON 处理 API 的全部内容。我们了解了 Java JSON 解析器、读取和写入示例。您可以从以下链接下载 Java 项目并试用它。
下载 Java JSON 项目
参考:JSONLint - 验证 JSON 数据的优秀 Web 工具JSON 处理参考实现 JSR353 JCP 页面