= GEP-7: JSON 支持 :icons: font .Metadata **** [horizontal,options="compact"] *编号*:: GEP-7 *标题*:: JSON 支持 *版本*:: 4 *类型*:: 功能 *状态*:: 最终版 *评论*:: 在 Groovy 1.8 中交付 *负责人*:: Guillaume Laforge *贡献者*:: Andres Almiray *创建日期*:: 2010-10-25 *最后修改日期* :: 2018-10-12 **** == 摘要: JSON 支持 提供构建器/解析器组合,以类似于处理 XML 的方式处理 JSON 格式的数据。 == 理由 JSON 已在网络上无处不在。RESTful 服务以 POX (Plain Old 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' // Map 也是对象的有效值 address( city: 'Paris', country: 'France', zip: 12345, ) married true conferences 'JavaOne', 'Gr8conf' } } // 创建由 Map (Json 对象) 和 List (Json 数组) 组成的数据结构 assert root instanceof Map println builder.toString() // 打印 (不带格式) {"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()` 接受一个可变参数的值。这里有一些例子: ``` builder.foo "foo" // 生成 {foo: "foo"} ``` ``` builder([{ foo 'foo' }]) // 生成 [{"foo": "foo"}] ``` ``` builder([[ foo: 'foo' ]]) // 生成,与上面相同 [{"foo": "foo"}] ``` ``` builder { elem 1, 2, 3 } // 生成 { "elem": [1, 2, 3] } ``` 当在构建器上调用不带参数的方法时,会将一个空的 JSON 对象与该键关联: ``` builder.element() // 生成 { "element": {} } ``` 您还可以传递一个 Map 和一个闭包参数: ``` builder.person(name: "Guillaume", age: 33) { town "Paris" } // 生成 {"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 和 List 层次结构。 ``` 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 实现 * http://json.org/[json.org] * http://tools.ietf.org/html/rfc4627[RFC-4627] * http://json-lib.sourceforge.net/[json-lib] === 邮件列表讨论 * https://marc.info/?l=groovy-dev&m=129623197505984&w=2[groovy-dev: 1.8 中内置 JSON 支持] === JIRA 问题 * https://issues.apache.org/jira/browse/GROOVY-4644[GROOVY-4644: JSON 支持:为 JSON 内容提供解析器和构建器] == 更新历史 3 (2011-02-02):: 从 Codehaus wiki 提取的版本 4 (2018-10-16):: 大量细微调整

GEP-7