8 月 3 日发布的 JSON-P 1.1 的第一个早期草案(即 JSON-P 1.1 EDR1)将在这篇抢先看的文章中介绍。您可能知道,Java API for JSON Processing 1.0 (JSR 353) 是 Java EE 7 中添加的标准 JSON Processing API。现在,JSON-P 正在更新为新版本 JSON-P 1.1,也称为 JSR 374 。当前版本带有基于 JSON 的新功能,例如 JSON Patch、JSON Pointer、JSON Merge Patch 和 Java SE 8 支持,每一项都已计划成为 Java EE 8 的一部分。我们将简要介绍当前值得注意的是与小示例结合在一起,以便您可以自己尝试草稿版本和/或获得有关新实现功能的一些想法。
在检查 JSON-P 1.1 API 时,我们发现了 5 个值得注意的类,每个类位于
javax.json
包中,如下所示:
- JsonUtil
- Json指针
- Json补丁
- JsonMerge补丁
- stream.JsonCollectors
javax.json.JsonUtil
JsonUtil
类是一个实用程序类,在 1.1 API 中可用。它包含一个名为
toJson
的类方法,它接受
一个 JSON 字符串
作为方法参数。此静态成员操作指定的 JSON 字符串以计算并返回
相应的 JSON 值
。
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
<1>类方法与提供的 JSON 字符串的简单用法。 |
<2>由于给定的JSON结构是一个JSON数组,我们可以将其转换为JsonArray。 |
javax.json.JsonPointer
JSON 指针是
IETF RFC 6901
规范。 JSON-P 1.1 为此规范提供了一个名为
JsonPointer
的具体不可变表示模块。
JsonPointer
类允许您通过指针签名检索目标 JSON 文档中的特定值。 JSON 指针语法以 Unicode 字符指定,由零个或多个引用标记的序列组成。每个指针必须以 '/' 字符开头,除非您想要使用空字符串作为指针(例如
""
)获取整个 JSON 文档。
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
<1>可以为
foo
数组定义3个不同的指针。要获取整个 foo 数组,指针必须是
"/foo"
。如果你想接收 foo 的第一个元素(即
'bar'
),你需要
"/foo/0"
组合。此外,您还可以使用
"/foo/1"
指针检索第二个元素。
|
<2>要找到值
0
,
"\"
是
''
的指针。
|
<3>当字符出现在引用令牌中时,'/'需要编码为'~1'。在这种情况下,我们的指针应该是
"/a~1b"
。
|
<4>这种键值对没有任何编码转换。
"/c%d"
只是足够的指针字符串。
|
<5>"/e^f"
只是为我们得到值 3。
|
<6>"/i\\j"
让我们找到值 5。
|
<7>
'k\"l'
的指针签名是
"/k\"l"
。
|
<8>'~'需要被编码为'~0',所以我们的指针将是
"/m~0n"
。
|
<9>要到达
s
的第一个元素
{'t':'u'}
,签名必须定义为
"/s/0"
;但是,我们的重点是检索
't'
'u'
'。因此,我们使用以下签名
"/s/0/t"
。
|
<10>JsonPointer 定义了一个用户定义的构造函数,它接受一个 JSON 指针字符串。在我们的例子中,签名是
"/ "
其中引用了
' ': 7
对。
|
<11>使用
getValue
方法,我们找到key的值。
|
或者,您可以添加一个 JSON 值,用另一个值替换一个 JSON 值,或者使用
JsonPointer
类的以下重载方法删除指定 JSON 结构中的 JSON 值:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
例如 ,下面是一个代码片段,显示了根据给定 JSON 字符串进行的添加操作:
JsonPointer类的add操作示例
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
修改后的对象的形状为:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
javax.json.JsonPatch
另一个
IETF RFC 6902
规范已在 JSON-P 1.1 中进行了改编。 JSON Patch 使用必须包含一个或多个特定补丁操作的 JSON 数组。有6种Patch操作即;添加、删除、替换、移动、复制和测试。在给出一组操作时,JSON Patch 应用于目标 JSON 文档。
JsonPatch
类体现了 Java 规范的能力。
您可以通过两种方式使用
JsonPatch
-
-
-
使用
JsonArray
实例化JsonPatch
。 -
适用于
JsonPatchBuilder
。
-
使用
第一种方法:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
<1>每个JSON Patch操作(即对象)都必须定义在一个JSON数组中,一般称为 JSON Patch 文档。当前的 JSON Patch 文档由 3 个 JSON Patch 对象组成,所有这些对象都按顺序应用于我们的目标 JSON 文档。 |
<2>我们第一个应用的操作是
复制
操作。该操作负责将指定位置的值复制到目标位置。该操作必须包含一个
from
成员,它是一种表示 JSON 指针值的 JSON 字符串类型。该操作应该将
名称
成员的值
Ali
复制到我们的目标成员的值(
nickname
)。
|
<3>顺序中的下一个操作是
remove
操作。只有两个主要的操作成员(
op
和
path
)必须包含才能使操作成功。此操作将删除
爱好
的第二个元素(即
graffiti
)。
|
<4>最后一个patch对象是关于JSON Patch文档中的
add
操作。该对象必须包含一个
value
成员,其内容指定要添加的值。在我们的例子中,指向
cycling
JSON 字符串的值被添加到数组的末尾。 JSON 指针
/hobbies/-
指的是
hobbies
的最后一个索引。
|
<5>我们简单地用JSON Patch文档创建一个新的
JsonPatch
对象。
|
<6>指定的补丁操作应用于我们的目标JSON文档,然后我们得到结果JSON对象。 |
注意:我们强烈建议您查看 JSON Patch 的其余操作! |
!IMPORTANT!: 每个操作对象必须只包含一个 op 成员,它表示操作值。每个操作对象必须只包含一个 路径 成员,其值必须是包含 JSON-Pointer 签名的字符串。 JSON Patch 对象的成员排序没有特权。 |
A) 转换后的 JSON 对象:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
您还可以使用
JsonPatchBuilder
类执行前面的场景。
第二种方法:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
B)结果与A相同:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
javax.json.JsonMergePatch
JSON Merge Patch
(RFC 7386)
的实现是 JSON 领域的新标准,已添加到 JSON-P 1.1 API 中。
JsonMergePatch
类有两个类方法。当
mergePatch
静态方法将指定的补丁应用到指定的目标时,
diff
方法从 JSON 源对象和 JSON 目标对象生成一个 JSON 合并补丁。
mergePatch 的使用示例:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
<1>我们的目标 JSON 资源。 |
<2>我们的合并补丁文档负责将合并补丁与目标资源的当前内容进行比较,以确定要应用于目标对象的特定更改操作集。这个补丁告诉我们的是,我们想用 30 替换 age 的值,删除 昵称 成员,添加一个新的 电子邮件 成员,替换 hobbies 数组,并保持 name 成员不变。 |
<3>静态方法
mergePatch
有两个参数:目标JSON文档和合并补丁文档。如果补丁不是 JSON 对象,则结果将用整个补丁替换整个目标。将补丁应用于目标对象后,您应该会看到一个新的 JSON 对象应用了一组操作。
|
C)返回的结果
mergePatch
:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
目标 | 修补 | 合并结果 |
---|---|---|
{“A”: [
|
{“一个”:[1]} |
{“一个”:[1]} |
{“一”:“乙”} |
{“一个”:“c”} |
{“一个”:“c”} |
{“一”:“乙”} |
{“公元前”} |
{“一”:“乙”, |
{“一”:“乙”} |
{“一个”:空} |
{} |
{“一”:“乙”,
|
{“一个”:空} |
{“公元前”} |
{"a":["b"]} |
{“一个”:“c”} |
{“一个”:“c”} |
{“一个”:“c”} |
{"a":["b"]} |
{"a":["b"]} |
{“A”: {
|
{“A”: {
|
{“A”: {
|
diff 的用法示例:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
<1> 结果将显示源和目标之间存在一些差异。这些差异指向实际的 JSON 合并路径。如果我们使用返回的 JSON 合并补丁和源对象调用
mergePatch
方法,将获得当前目标对象。
|
D) 差异结果:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
javax.json.stream.JsonCollectors
与
Collectors
一样,
JsonCollectors
实用程序类有一些有用的方法,可以创建一个
Collector
,它将输入的
JsonValue
元素累积到一个可变的结果容器中,该容器可以是
JsonArray
或
JsonObject
。我们需要使用
collect
方法与
JsonCollectors
一起终止流。有四种实用方法,如下所示:
-
toJsonArray()
:- 将流的 JsonValue 元素添加到 JsonArray 中
-
toJsonObject (Function key, Function value)
:- 将流的 JsonValue 元素添加到使用键和值创建的 JsonObject 中。
-
groupingBy (Function classifier)
:- 使用 Function 分类器将 JsonValue 流元素分组到 JsonObject 中。
-
groupingBy (Function classifier, Collector downstream)
:- 使用 Function 分类器将 JsonValue 流元素分组到 JsonObject 中。
- 使用 Collector 在每个组中执行归约。
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
接下来的 3 个示例说明了我们如何根据 用户 数组分别使用可用的方法。
E1) 找到年龄大于或等于 25 岁的用户,然后将他们的名字添加到 JsonArray 中:
toJsonArray()
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
结果:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
E2) 将姓名-爱好对添加到 JsonObject 中:
toJsonObject(…):
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
结果:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
E3) 喜欢开车或徒步旅行的群组用户:
分组(…)
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>
结果是:
JsonValue users = JsonUtil.toJson( <1>
"[ " +
" { 'name': 'Ali', " +
" 'age': 25, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking', 'graffiti']}, " +
" { 'name': 'Veli', " +
" 'age': 23, " +
" 'gender': 'M', " +
" 'hobbies': [ " +
" 'hiking']}, " +
" { 'name': 'Ayşe', " +
" 'age': 26, " +
" 'gender': 'F', " +
" 'hobbies': [ " +
" 'driving', 'fishing']} " +
" ]");
JsonArray array = (JsonArray) users; <2>