Java JSON-P
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,在现代Web应用和API中被广泛使用。Java JSON Processing API(JSON-P)是Java EE的标准API,提供了在Java应用程序中处理JSON数据的便捷方式。
JSON-P简介
JSON-P提供了两种处理JSON数据的方法:
- 对象模型API - 通过树状结构在内存中表示JSON数据
- 流API - 以事件驱动的方式处理JSON数据,类似于XML的StAX
无论您需要解析、生成、转换还是查询JSON数据,JSON-P都提供了必要的工具来简化这些任务。
JSON-P是Jakarta EE(以前的Java EE)的一部分,它是标准的JSON处理API。不要与JSON-B(JSON Binding)混淆,后者专注于Java对象和JSON之间的自动转换。
使用JSON-P
首先,您需要添加JSON-P依赖到您的项目中。如果您使用Maven,可以添加以下依赖:
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.1.4</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.1.4</version>
<scope>runtime</scope>
</dependency>
对象模型API
对象模型API提供了在内存中创建、解析和操作JSON的方法。
创建JSON对象
// 创建JSON对象
JsonBuilderFactory factory = Json.createBuilderFactory(null);
JsonObject person = factory.createObjectBuilder()
.add("name", "张三")
.add("age", 30)
.add("isStudent", false)
.add("address", factory.createObjectBuilder()
.add("street", "和平路")
.add("city", "上海")
.add("zipCode", "200000"))
.add("phoneNumbers", factory.createArrayBuilder()
.add("123-456-7890")
.add("987-654-3210"))
.build();
// 输出JSON
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = Json.createWriter(stringWriter);
jsonWriter.writeObject(person);
jsonWriter.close();
System.out.println(stringWriter.toString());
输出结果:
{"name":"张三","age":30,"isStudent":false,"address":{"street":"和平路","city":"上海","zipCode":"200000"},"phoneNumbers":["123-456-7890","987-654-3210"]}
解析JSON字符串
// JSON字符串
String jsonString = "{\"name\":\"李四\",\"age\":25,\"city\":\"北京\"}";
// 解析JSON
JsonReader jsonReader = Json.createReader(new StringReader(jsonString));
JsonObject jsonObject = jsonReader.readObject();
jsonReader.close();
// 访问JSON数据
String name = jsonObject.getString("name");
int age = jsonObject.getInt("age");
String city = jsonObject.getString("city");
System.out.println("姓名: " + name);
System.out.println("年龄: " + age);
System.out.println("城市: " + city);
输出结果:
姓名: 李四
年龄: 25
城市: 北京
流API
流API让您能够以事件驱动的方式解析和生成JSON,对于处理大型JSON文档特别有效。
解析JSON流
String jsonString =
"{ \"name\": \"王五\", " +
"\"skills\": [\"Java\", \"Python\", \"JavaScript\"], " +
"\"experience\": 5 }";
JsonParser parser = Json.createParser(new StringReader(jsonString));
while (parser.hasNext()) {
JsonParser.Event event = parser.next();
switch (event) {
case KEY_NAME:
System.out.print("键: " + parser.getString() + ", ");
break;
case VALUE_STRING:
System.out.println("字符串值: " + parser.getString());
break;
case VALUE_NUMBER:
System.out.println("数字值: " + parser.getInt());
break;
case VALUE_TRUE:
System.out.println("布尔值: true");
break;
case VALUE_FALSE:
System.out.println("布尔值: false");
break;
default:
// 处理其他事件类型
}
}
parser.close();
输出结果:
键: name, 字符串值: 王五
键: skills,
字符串值: Java
字符串值: Python
字符串值: JavaScript
键: experience, 数字值: 5
生成JSON流
StringWriter writer = new StringWriter();
JsonGenerator generator = Json.createGenerator(writer);
generator.writeStartObject()
.write("title", "Java编程指南")
.write("author", "赵六")
.write("year", 2023)
.writeStartArray("chapters")
.writeStartObject()
.write("chapterNumber", 1)
.write("title", "Java基础")
.writeEnd()
.writeStartObject()
.write("chapterNumber", 2)
.write("title", "面向对象编程")
.writeEnd()
.writeEnd()
.writeEnd();
generator.close();
System.out.println(writer.toString());
输出结果:
{"title":"Java编程指南","author":"赵六","year":2023,"chapters":[{"chapterNumber":1,"title":"Java基础"},{"chapterNumber":2,"title":"面向对象编程"}]}
JSON指针与补丁操作
JSON-P 1.1引入了对JSON Pointer和JSON Patch的支持,使得查询和修改JSON文档变得更加简单。
JSON指针
JSON指针允许您使用路径表达式引用JSON文档中的特定部分。
String jsonString = "{\"person\":{\"name\":\"陈七\",\"address\":{\"city\":\"广州\"}}}";
JsonReader reader = Json.createReader(new StringReader(jsonString));
JsonObject jsonObject = reader.readObject();
// 创建JSON指针
JsonPointer pointer = Json.createPointer("/person/address/city");
// 使用指针获取值
JsonString city = (JsonString) pointer.getValue(jsonObject);
System.out.println("城市: " + city.getString()); // 输出: 城市: 广州
// 使用指针添加/替换值
JsonObject updatedJson = pointer.replace(jsonObject, Json.createValue("深圳"));
System.out.println(updatedJson);
JSON补丁
JSON补丁提供了一种标准方式来描述对JSON文档的更改。
JsonObject source = Json.createObjectBuilder()
.add("firstName", "John")
.add("lastName", "Smith")
.add("age", 25)
.build();
// 创建一个JSON补丁
JsonPatch patch = Json.createPatchBuilder()
.replace("/firstName", "Jane")
.remove("/age")
.add("/gender", "female")
.build();
// 应用补丁
JsonObject result = patch.apply(source);
System.out.println(result);
输出结果:
{"firstName":"Jane","lastName":"Smith","gender":"female"}
实际案例:构建REST API响应
以下是一个使用JSON-P构建REST API响应的实际案例:
public class ProductService {
public String getProductDetails(int productId) {
// 模拟从数据库获取产品数据
Product product = findProductById(productId);
if (product == null) {
return createErrorResponse("产品不存在");
}
// 构建JSON响应
JsonBuilderFactory factory = Json.createBuilderFactory(null);
JsonObject response = factory.createObjectBuilder()
.add("status", "success")
.add("product", factory.createObjectBuilder()
.add("id", product.getId())
.add("name", product.getName())
.add("price", product.getPrice())
.add("description", product.getDescription())
.add("inStock", product.isInStock())
.add("categories", factory.createArrayBuilder(product.getCategories()))
.add("attributes", createAttributesJson(factory, product.getAttributes())))
.build();
StringWriter stringWriter = new StringWriter();
Map<String, Object> config = new HashMap<>();
config.put(JsonGenerator.PRETTY_PRINTING, true);
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
JsonWriter jsonWriter = writerFactory.createWriter(stringWriter);
jsonWriter.writeObject(response);
jsonWriter.close();
return stringWriter.toString();
}
private String createErrorResponse(String message) {
JsonObject error = Json.createObjectBuilder()
.add("status", "error")
.add("message", message)
.build();
StringWriter writer = new StringWriter();
JsonWriter jsonWriter = Json.createWriter(writer);
jsonWriter.writeObject(error);
jsonWriter.close();
return writer.toString();
}
private JsonObject createAttributesJson(JsonBuilderFactory factory, Map<String, String> attributes) {
JsonObjectBuilder builder = factory.createObjectBuilder();
for (Map.Entry<String, String> entry : attributes.entrySet()) {
builder.add(entry.getKey(), entry.getValue());
}
return builder.build();
}
// 模拟数据库查询
private Product findProductById(int productId) {
// 此处应该是实际的数据库查询
if (productId == 1001) {
Product product = new Product();
product.setId(1001);
product.setName("高性能笔记本电脑");
product.setPrice(6999.99);
product.setDescription("16GB RAM, 512GB SSD, Intel i7处理器");
product.setInStock(true);
List<String> categories = new ArrayList<>();
categories.add("电子产品");
categories.add("电脑");
product.setCategories(categories);
Map<String, String> attributes = new HashMap<>();
attributes.put("brand", "TechMaster");
attributes.put("color", "银色");
attributes.put("warranty", "2年");
product.setAttributes(attributes);
return product;
}
return null;
}
}
上面的例子展示了如何在实际应用中使用JSON-P创建复杂的JSON响应。这种方法特别适用于需要精确控制JSON结构的场景。对于简单的Java对象到JSON的转换,您可能更倾向于使用JSON-B(JSON Binding)。
处理大型JSON文档
当需要处理非常大的JSON文档时,流API是更高效的选择:
public static void parseAndAggregateData(InputStream inputStream) throws IOException {
JsonParser parser = Json.createParser(inputStream);
// 跟踪当前状态
String currentCategory = null;
int totalItems = 0;
double totalSales = 0;
// 事件驱动解析
while (parser.hasNext()) {
JsonParser.Event event = parser.next();
switch (event) {
case KEY_NAME:
if (parser.getString().equals("category")) {
// 下一个事件是类别值
parser.next();
currentCategory = parser.getString();
System.out.println("处理类别: " + currentCategory);
} else if (parser.getString().equals("price") &&
currentCategory != null &&
currentCategory.equals("electronics")) {
// 如果是电子产品类别的价格
parser.next();
totalSales += parser.getBigDecimal().doubleValue();
totalItems++;
}
break;
case END_OBJECT:
// 可以在这里添加对象结束的处理
break;
default:
// 其他事件处理
}
}
System.out.println("电子产品统计:");
System.out.println("总项目数: " + totalItems);
System.out.println("总销售额: " + totalSales);
parser.close();
}
总结
Java JSON-P提供了一套全面的API,用于处理JSON数据:
- 对象模型API适用于需要在内存中操作整个JSON文档的场景
- 流API对于处理大型JSON文档或仅需要访问特定部分的场景更高效
- JSON指针和JSON补丁提供了引用和修改JSON文档的标准方式
JSON-P作为Java标准API,提供了跨平台一致性和可靠性,是处理JSON数据的良好选择。
练习
- 创建一个JSON对象,表示一个学生,包含姓名、年龄、课程列表(数组)和地址(嵌套对象)。
- 解析以下JSON字符串并提取所有书籍的标题和作者:
json
{
"library": {
"name": "城市图书馆",
"books": [
{"title": "Java编程", "author": "张三", "year": 2020},
{"title": "Python基础", "author": "李四", "year": 2019},
{"title": "Web开发入门", "author": "王五", "year": 2021}
]
}
} - 使用JSON补丁,修改一个JSON对象,将价格增加10%,并添加一个"discount"字段。
参考资源
通过掌握JSON-P,您将能够在Java应用程序中有效地处理各种JSON格式数据,无论是简单还是复杂的场景。