Json/Xml简介和处理模型

JSON

json简介

  JSON是一种基于文本的数据交换格式,源自JavaScript,用于Web服务和其他连接的应用程序。以下部分介绍了JSON语法,JSON使用概述以及生成和解析JSON的最常用方法的说明。

  • JSON语法

  JSON只定义了两个数据结构:对象和数组。对象是一组名称 - 值对,而数组是值列表。JSON定义了七种值类型:字符串,数字,对象,数组,true,false和null。

  以下示例显示包含名称 - 值对的示例对象的JSON数据。名称的值"phoneNumbers"是一个数组,其元素是两个对象。

{
   "firstName": "Duke",
   "lastName": "Java",
   "age": 18,
   "streetAddress": "100 Internet Dr",
   "city": "JavaTown",
   "state": "JA",
   "postalCode": "12345",
   "phoneNumbers": [
      { "Mobile": "111-111-1111" },
      { "Home": "222-222-2222" }
   ]
}

 JSON具有以下语法:

  • 对象用大括号({}括起来,它们的名称 - 值对用逗号(,分隔,一对中的名称和值用冒号(:分隔对象中的名称是字符串,而值可以是七种值类型中的任何一种,包括另一个对象或数组。

  • 数组括在括号([])中,它们的值用逗号(,分隔数组中的每个值可以是不同的类型,包括另一个数组或对象。

  • 当对象和数组包含其他对象或数组时,数据具有树状结构。

  • JSON的使用

  JSON通常用作通用格式,用于序列化和反序列化通过Internet相互通信的应用程序中的数据。这些应用程序使用不同的编程语言创建,并在不同的环境中运行。JSON适用于这种情况,因为它是一个开放标准,易于读写,并且比其他表示更紧凑。

  RESTful Web服务广泛使用JSON作为请求和响应中的数据格式。HTTP标头用于指示请求或响应的内容是JSON数据。

Content-Type: application/json

  JSON表示通常比XML表示更紧凑,因为JSON没有结束标记。与XML不同,JSON没有广泛接受的模式来定义和验证JSON数据的结构。

  • 生成和解析JSON数据

为了生成和解析JSON数据,有两种编程模型,类似于用于XML文档的编程模型。

  • 对象模型创建一个表示内存中JSON数据的树。然后可以导航,分析或修改树。这种方法最灵活,允许进行需要访问树的完整内容的处理。但是,它通常比流模型慢,需要更多内存。对象模型通过一次导航整个树来生成JSON输出。

  • 流模型使用基于事件的解析器,一次读取一个元素的JSON数据。当对象或数组开始或结束,找到键或找到值时,解析器生成事件并停止处理。应用程序代码可以处理或丢弃每个元素,然后解析器继续执行下一个事件。这种方法适用于本地处理,其中元素的处理不需要来自其余数据的信息。流模型通过一次使用一个元素进行函数调用来生成给定流的JSON输出。

有许多JSON生成器和解析器可用于不同的编程语言和环境。Java EE平台中的JSON处理描述了Java API for JSON Processing(JSR 374)提供的功能。

Java EE包括对JSR 374的支持,JSR 374提供了一个API,用于使用生成和解析JSON数据中描述的对象模型或流模型来解析,转换和查询JSON数据JSON Processing的Java API包含以下包:

  • javax.json软件包包含一个reader接口,一个writer接口,一个用于对象模型的模型构建器接口,以及用于JSON元素的实用程序类和Java类型。该软件包还包括几个实现其他JSON相关标准的类:JSON指针, JSON补丁JSON合并补丁这些标准用于检索,转换或操纵对象模型中的值。表20-1列出了此包中的主要类和接口。

  • javax.json.stream包包含解析器接口和流模型的生成器接口。表20-2 列出了此包中的主要类和接口。

  • javax.json.spi软件包包含一个服务提供程序接口(SPI),用于插入JSON处理对象的实现。此包包含JsonProvider该类,该类包含服务提供者实现的方法。

具体参考官方文档:https://javaee.github.io/tutorial/jsonp002.html#CHDIHCEG

 

Java EE平台中的JSON  processing

  • 使用对象模型API

  对象模型API的四个用例:从JSON数据创建对象模型,从应用程序代码创建对象模型,导航对象模型以及将对象模型编写到流中。

    • 从JSON数据创建对象模型

  以下代码演示了如何从文本文件中的JSON数据创建对象模型:

import java.io.FileReader;
import javax.json.Json;
import javax.json.JsonReader;
import javax.json.JsonStructure;
...
JsonReader reader = Json.createReader(new FileReader("jsondata.txt"));
JsonStructure jsonst = reader.read();

  对象引用jsonst可以是类型JsonObject或类型JsonArray,具体取决于文件的内容。JsonObject 并且JsonArray是亚型JsonStructure此引用表示树的顶部,可用于导航树或将其作为JSON数据写入流。

    • 从应用程序代码创建对象模型

  以下代码演示了如何从应用程序代码创建对象模型:

import javax.json.Json;
import javax.json.JsonObject;
...
JsonObject model = Json.createObjectBuilder()
   .add("firstName", "Duke")
   .add("lastName", "Java")
   .add("age", 18)
   .add("streetAddress", "100 Internet Dr")
   .add("city", "JavaTown")
   .add("state", "JA")
   .add("postalCode", "12345")
   .add("phoneNumbers", Json.createArrayBuilder()
      .add(Json.createObjectBuilder()
         .add("type", "mobile")
         .add("number", "111-111-1111"))
      .add(Json.createObjectBuilder()
         .add("type", "home")
         .add("number", "222-222-2222")))
   .build(); 

  对象引用model表示树的顶部,它是通过嵌套对add方法的调用并通过调用build方法构建的 JsonObjectBuilder类包含下列 add方法:

JsonObjectBuilder add(String name, BigDecimal value)
JsonObjectBuilder add(String name, BigInteger value)
JsonObjectBuilder add(String name, boolean value)
JsonObjectBuilder add(String name, double value)
JsonObjectBuilder add(String name, int value)
JsonObjectBuilder add(String name, JsonArrayBuilder builder)
JsonObjectBuilder add(String name, JsonObjectBuilder builder)
JsonObjectBuilder add(String name, JsonValue value)
JsonObjectBuilder add(String name, long value)
JsonObjectBuilder add(String name, String value)
JsonObjectBuilder addNull(String name) 

  本JsonArrayBuilder类包含类似的add没有一个名称(键)参数的方法。您可以通过将新JsonArrayBuilder对象或新JsonObjectBuilder对象传递给相应的add方法来嵌套数组和对象,如此示例所示。

  生成的树表示来自JSON语法的JSON数据 

 

    • 导航对象模型

  以下代码演示了一种导航对象模型的简单方法:

import javax.json.JsonValue;
import javax.json.JsonObject;
import javax.json.JsonArray;
import javax.json.JsonNumber;
import javax.json.JsonString;
...
public static void navigateTree(JsonValue tree, String key) {
   if (key != null)
      System.out.print("Key " + key + ": ");
   switch(tree.getValueType()) {
      case OBJECT:
         System.out.println("OBJECT");
         JsonObject object = (JsonObject) tree;
         for (String name : object.keySet())
            navigateTree(object.get(name), name);
         break;
      case ARRAY:
         System.out.println("ARRAY");
         JsonArray array = (JsonArray) tree;
         for (JsonValue val : array)
            navigateTree(val, null);
         break;
      case STRING:
         JsonString st = (JsonString) tree;
         System.out.println("STRING " + st.getString());
         break;
      case NUMBER:
         JsonNumber num = (JsonNumber) tree;
         System.out.println("NUMBER " + num.toString());
         break;
      case TRUE:
      case FALSE:
      case NULL:
         System.out.println(tree.getValueType().toString());
         break;
   }
}

  该方法navigateTree可以与内置的模型被用来 创建从JSON数据对象模型和 创建从应用程序代码的对象模型如下:

navigateTree(model, null);

  该navigateTree方法有两个参数:JSON元素和键。该键仅用于帮助打印对象内的键值对。树中的元素由JsonValue类型表示。如果元素是对象或数组,则对对象或数组中包含的每个元素进行此方法的新调用。如果元素是值,则将其打印到标准输出。

  该JsonValue.getValueType方法将元素标识为对象,数组或值。对于对象,该JsonObject.keySet方法返回一组包含对象中键的字符串,该 JsonObject.get(String name)方法返回其键所在元素的值name对于数组,JsonArray实现 List<JsonValue>接口。您可以将增强for循环与 Set<String>实例返回的JsonObject.keySet实例一起使用JsonArray,如本示例所示。

从Application Code创建对象navigateTree模型中构建的模型方法产生以下输出:

OBJECT
Key firstName: STRING Duke
Key lastName: STRING Java
Key age: NUMBER 18
Key streetAddress: STRING 100 Internet Dr
Key city: STRING JavaTown
Key state: STRING JA
Key postalCode: STRING 12345
Key phoneNumbers: ARRAY
OBJECT
Key type: STRING mobile
Key number: STRING 111-111-1111
OBJECT
Key type: STRING home
Key number: STRING 222-222-2222

  

    • 将对象模型写入流

  创建从JSON数据的对象模型创建从应用程序代码的对象模型的对象可被写入到使用一个流JsonWriter 类,如下所示:

import java.io.StringWriter;
import javax.json.JsonWriter;
...
StringWriter stWriter = new StringWriter();
JsonWriter jsonWriter = Json.createWriter(stWriter);
jsonWriter.writeObject(model);
jsonWriter.close();

String jsonData = stWriter.toString();
System.out.println(jsonData);

  该Json.createWriter方法将输出流作为参数。该JsonWriter.writeObject方法将对象写入流。该 JsonWriter.close方法关闭基础输出流。

  以下示例使用try-with-resources自动关闭JSON编写器:

StringWriter stWriter = new StringWriter();
try (JsonWriter jsonWriter = Json.createWriter(stWriter)) {
   jsonWriter.writeObject(model);
}

String jsonData = stWriter.toString();
System.out.println(jsonData);
 
  • 使用Streaming API

    • 使用解析器读取JSON数据

 流API是解析JSON文本的最有效方法。以下代码演示了如何创建JsonParser对象以及如何使用事件解析JSON数据:

import javax.json.Json;
import javax.json.stream.JsonParser;
...
JsonParser parser = Json.createParser(new StringReader(jsonData));
while (parser.hasNext()) {
   JsonParser.Event event = parser.next();
   switch(event) {
      case START_ARRAY:
      case END_ARRAY:
      case START_OBJECT:
      case END_OBJECT:
      case VALUE_FALSE:
      case VALUE_NULL:
      case VALUE_TRUE:
         System.out.println(event.toString());
         break;
      case KEY_NAME:
         System.out.print(event.toString() + " " +
                          parser.getString() + " - ");
         break;
      case VALUE_STRING:
      case VALUE_NUMBER:
         System.out.println(event.toString() + " " +
                            parser.getString());
         break;
   }
} 

此示例包含三个步骤。

  1. 通过调用Json.createParser静态方法获取解析器实例

  2. 使用JsonParser.hasNext和 JsonParser.next方法迭代解析器事件

  3. 对每个元素执行本地处理。

该示例显示了解析器中的十种可能的事件类型。解析器的next方法将其推进到下一个事件。对于事件类型KEY_NAMEVALUE_STRINGVALUE_NUMBER,您可以通过调用方法获取元素的内容JsonParser.getString对于 VALUE_NUMBER事件,您还可以使用以下方法:

  • JsonParser.isIntegralNumber

  • JsonParser.getInt

  • JsonParser.getLong

  • JsonParser.getBigDecimal

有关javax.json.stream.JsonParser 更多信息,请参阅该接口的Java EE API参考

此示例的输出如下:

START_OBJECT
KEY_NAME firstName - VALUE_STRING Duke
KEY_NAME lastName - VALUE_STRING Java
KEY_NAME age - VALUE_NUMBER 18
KEY_NAME streetAddress - VALUE_STRING 100 Internet Dr
KEY_NAME city - VALUE_STRING JavaTown
KEY_NAME state - VALUE_STRING JA
KEY_NAME postalCode - VALUE_STRING 12345
KEY_NAME phoneNumbers - START_ARRAY
START_OBJECT
KEY_NAME type - VALUE_STRING mobile
KEY_NAME number - VALUE_STRING 111-111-1111
END_OBJECT
START_OBJECT
KEY_NAME type - VALUE_STRING home
KEY_NAME number - VALUE_STRING 222-222-2222
END_OBJECT
END_ARRAY
END_OBJECT

  

    • 使用生成器编写JSON数据

 以下代码演示了如何使用流API将JSON数据写入文件:

FileWriter writer = new FileWriter("test.txt");
JsonGenerator gen = Json.createGenerator(writer);
gen.writeStartObject()
   .write("firstName", "Duke")
   .write("lastName", "Java")
   .write("age", 18)
   .write("streetAddress", "100 Internet Dr")
   .write("city", "JavaTown")
   .write("state", "JA")
   .write("postalCode", "12345")
   .writeStartArray("phoneNumbers")
      .writeStartObject()
         .write("type", "mobile")
         .write("number", "111-111-1111")
      .writeEnd()
      .writeStartObject()
         .write("type", "home")
         .write("number", "222-222-2222")
      .writeEnd()
   .writeEnd()
.writeEnd();
gen.close();

此示例通过调用Json.createGenerator静态方法获取JSON生成器,该 方法将writer或输出流作为参数。该示例JSON数据写入到test.txt 通过嵌套的调用文件writewriteStartArraywriteStartObject,和writeEnd方法。JsonGenerator.close 方法关闭底层的编写器或输出流。

XML

XML简介

  • xml定义

  扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML使用DTD(document type definition)文档类型定义来组织数据;格式统一,跨平台和语言,早已成为业界公认的标准。
  XML是标准通用标记语言 (SGML) 的子集,非常适合 Web 传输。XML 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。

    • XML 指可扩展标记语言(EXtensible Markup Language)
    • XML 是一种标记语言,很类似 HTML
    • XML 的设计宗旨是传输数据,而非显示数据
    • XML 标签没有被预定义。您需要自行定义标签。
    • XML 被设计为具有自我描述性。
    • XML 是 W3C 的推荐标准

  XML 是各种应用程序之间进行数据传输的最常用的工具,并且在信息存储和描述领域变得越来越流行。

  XML 是独立于软件和硬件的信息传输工具。

  了解更多进入w3c网站了解:http://www.w3school.com.cn/xml/xml_intro.asp

XML处理模型(XML processing model)

  XML处理模型定义了如何将XML文档是由解释应用。 然后可以使用不同视图在屏幕上呈现文档,用于处理XML数据等。模型可以分为两个阶段:用于定义数据模型的XML管道和旨在使用的后XML管道数据模型。  

 

  • XML管道

  XML管道是参与每个步骤的规范的XML处理器。如何以及何时在XML处理器中进行规范(由Unicode,IETF,W3C或其他组织定义)。

 

  • 数据模型

  XML应用程序的期望是什么?基于已定义的子集规范:Unicode 3.1.0,RFC 2396,XML 1.0,命名空间,XML Base,XInclude,XML Schema和XLink / XPointer?或者仍然继续我们当前的方法(<7!),即每个XML应用程序定义自己的集合?当然,答案并不容易,但希望Infoset将减少XML管道中涉及的规范数量:Infoset,XInclude,XML Schema,XLink / XPointer(<4!)。PSV Infoset减少了这个数字:PSVI,XInclude,XLink / XPointer。

  这导致我们采用通用数据模型。由于历史原因,在W3C中开发了几个数据模型:DOM,XPath 1.0,Infoset,PSV Infoset,XML Query等。它们中的每一个都是向前一个添加/删除信息。例如,最近的XQuery 1.0和XPath 2.0数据模型正在PSV Infoset之上添加参考节点信息项。

  DOM数据模型添加了更多信息,例如CDATA部分或实体引用。由于向后兼容性原因,更改DOM数据模型会很困难,但是,使用加载和保存模型,DOM能够在不破坏向后兼容性的情况下满足Infoset的要求。我们还能够使用抽象模式/ PSVI对象模型来表示PSV信息集。恕我直言,应该针对PSVI定义每个新的XML应用程序,包括XInclude。

详细参考W3C:https://www.w3.org/2001/06/ProcessingModel-plh.html

原文地址:https://www.cnblogs.com/xiaohuomiao/p/10628196.html