GEP-7
摘要:JSON 支持
提供一个构建器/解析器组合,用于以类似于 XML 的方式处理 JSON 格式的数据。
理由
JSON 已成为 Web 上无处不在的格式。RESTful 服务在 POX(普通旧 XML)和 JSON 格式之间交换数据。Groovy 在使用 MarkupBuilder、XmlSlurper 和 XmlParser 生成/使用 XML 方面有出色的支持,但缺乏对 JSON 的这种支持。此 GEP 致力于通过提供兼容的构建器方法来弥补这一不足。
生成 JSON
建议使用以下构建器语法
def builder = new groovy.json.JsonBuilder()
def root = builder.people {
person {
firstName 'Guillame'
lastName 'Laforge'
// Maps are valid values for objects too
address(
city: 'Paris',
country: 'France',
zip: 12345,
)
married true
conferences 'JavaOne', 'Gr8conf'
}
}
// creates a data structure made of maps (Json object) and lists (Json array)
assert root instanceof Map
println builder.toString()
// prints (without formatting)
{"people": {
"person": {
"firstName": "Guillaume",
"lastName": "Laforge",
"address": {
"city": "Paris",
"country": "France",
"zip": 12345
},
"married": true,
"conferences": [
"JavaOne",
"Gr8conf"
]
}
}
有效节点值包括:Number
、String
、GString
、Boolean
、Map
、List
。null
用于对象引用。数组不能为 null,但可以为空。任何其他值都会导致抛出 IAE(或更专业的异常)。
特殊情况
需要考虑一种特殊情况:当顶层节点导致匿名对象或数组时,或者对象在构建器上调用 call() 方法时,该方法需要一个 map 作为参数,对于数组,call() 需要一个包含值的 vararg。以下是一些示例
builder.foo "foo"
// produces
{foo: "foo"}
builder([{
foo 'foo'
}])
// produces
[{"foo": "foo"}]
builder([[
foo: 'foo'
]])
// produces, same as above
[{"foo": "foo"}]
builder {
elem 1, 2, 3
}
// produces
{ "elem": [1, 2, 3] }
当在构建器上调用方法而不带参数时,一个空的 JSON 对象与该键相关联
builder.element()
// produces
{ "element": {} }
您也可以传递一个 map 和一个闭包参数
builder.person(name: "Guillaume", age: 33) { town "Paris" }
// produces
{"name": "Guillaume", "age": 33, "town": "Paris}
以下调用,带有 map 和值,在 JSON 中没有有意义的表示(与 XML 不同),并会触发 JsonException
shouldFail(JsonException) {
builder.elem(a: 1, b: 2, "some text value")
}
在 map 和闭包中出现重叠键的情况下,闭包优先 - 此规则的视觉线索是闭包出现在 map 键/值对“之后”。
使用 JSON 本提案建议创建一个 JsonSlurper 类,它可以从字符串(以非流式方式)读取 JSON 并生成表示 JSON 对象和数组的 map 和列表层次结构。
String json = '{"person": {"firstName": "Guillaume", "lastName": "Laforge", "conferences": ["JavaOne", "Gr8conf"]}}'
def root = new JsonSlurper().parseText(json)
assert root instanceof Map
assert root.person.conferences instanceof List
assert root.person.firstName == 'Guillaume'
assert root.person.conferences[1] == 'Gr8conf'
JsonSlurper 的 API 应该在 parse* 方法变体方面与 XmlParser/XmlSlurper 提供的功能密切匹配。
参考资料和有用链接
JSON 规范和 Java 实现
邮件列表讨论
更新历史
- 3 (2011-02-02)
-
从 Codehaus wiki 中提取的版本
- 4 (2018-10-16)
-
大量细微调整