JSON(JavaScript对象表示法)是一种紧凑的文本文件格式,可用于存储和传输数据。 多年来,由于其易于阅读和解析,它已变得非常流行。 除此之外,每个JSON构造都应该是有效JavaScript,并且应该可以使用JavaScript的eval()函数对其进行评估。 后者使它在Web开发人员社区中很流行,因为可以轻松地在客户端评估从服务器接收的JSON数据。
JSON的流行创造了在服务器端也使用它的需求。 随着时间的流逝,已经开发出了支持读取和写入JSON数据的各种Java库(例如google-gson , flexjson或Jackson )。 因此,JSON处理成为Java EE规范的一部分只是时间问题。 在上一篇文章中,我介绍了Java EE 7的新并发功能。在本文中,我们要探讨JSON处理的新功能。 在这些介绍性的词之后,是时候介绍一些代码了。 以下代码显示了如何编写一个非常简单的JSON文件:
JsonObject model = Json.createObjectBuilder()
.add("firstName", "Martin")
.add("phoneNumbers", Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("mobile", "1234 56789"))
.add(Json.createObjectBuilder()
.add("home", "2345 67890")))
.build();
try (JsonWriter jsonWriter = Json.createWriter(new FileWriter(Paths.get(System.getProperty("user.dir"), "target/myData.json").toString()))) {
jsonWriter.write(model);
} catch (IOException e) {
LOGGER.severe("Failed to create file: " + e.getMessage());
}
使用构建器API,可以轻松地将下一个调用追加到上一个调用。 我仍然需要习惯于每次创建数组或对象时都必须调用createArrayBuilder()或createObjectBuilder()的事实。 读取JSON文件时,必须通过调用getValueType()确定当前正在读取的类型:
try (JsonReader jsonReader = Json.createReader(new FileReader(Paths.get(System.getProperty("user.dir"), "target/myData.json").toString()))) {
JsonStructure jsonStructure = jsonReader.read();
JsonValue.ValueType valueType = jsonStructure.getValueType();
if (valueType == JsonValue.ValueType.OBJECT) {
JsonObject jsonObject = (JsonObject) jsonStructure;
JsonValue firstName = jsonObject.get("firstName");
...
将完整的JSON文件映射到Java类的现有结构(类似于XML文件的JAX-B)的功能不是标准的一部分。 但是,除了JSON-P之外,JSON-P还提供了完整的流API,用于读取大量JSON数据:
try (FileWriter writer = new FileWriter(Paths.get(System.getProperty("user.dir"), "target/myStream.json").toString())) {
JsonGenerator gen = Json.createGenerator(writer);
gen
.writeStartObject()
.write("firstName", "Martin")
.writeStartArray("phoneNumbers")
.writeStartObject()
.write("mobile", 123456789)
.write("home", "2345 67890")
.writeEnd()
.writeEnd()
.writeEnd();
gen.close();
} catch (IOException e) {
LOGGER.severe("Failed to write to file: " + e.getMessage());
}
流式API的代码读取与普通API非常相似。 主要区别在于您必须使用writeEnd()标记数组或对象的结尾。 读取JSON文件看起来与[XML的流API(StAX)]( http://stax.codehaus.org/Home )非常相似:
try (FileReader fileReader = new FileReader(Paths.get(System.getProperty("user.dir"), "target/myStream.json").toString())) {
JsonParser parser = Json.createParser(fileReader);
while (parser.hasNext()) {
JsonParser.Event event = parser.next();
switch (event) {
case START_OBJECT:
LOGGER.info("{");
break;
case END_OBJECT:
LOGGER.info("}");
break;
...
刚刚说完以上代码看起来与StAX代码非常相似,让我们尝试通过文件大小和运行时来比较这两种实现。 下图显示了写入和读取具有100.000条目的JSON / XML文件的平均执行时间。
一项包含一个简单的对象,该对象具有名称和两个电话号码的数组:
{"firstName":"Martin","phoneNumbers":[{"mobile":123456789,"home":"2345 67890"}]}
这就是它在XML中的外观:
<firstName>Martin</firstName><phoneNumbers><mobile>123456789</mobile><home>234567890</home></phoneNumbers>
令人惊讶的是,在编写大文件时,StAX实现的速度要慢得多。 当我们仔细查看文件大小时,尽管XML文件包含相同的数据,但它却比JSON文件大1.31倍。
结论:JSON-P提供了用于JSON处理的标准API以及类似StAX的流API。 尽管它仍然缺乏对Java类结构的绑定,但是它的性能比StAX实现更好,但文件大小更紧凑。
- 源代码可以在我的github 仓库中找到。
PS:比较中使用的实现如下:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>stax</groupId>
<artifactId>stax</artifactId>
<version>1.2.0</version>
</dependency>
翻译自: https://www.javacodegeeks.com/2014/03/json-processing-json-p-tutorial.html