Changes

Jump to navigation Jump to search
2,880 bytes added ,  13:06, 2 July 2020
This [[Module Library|XQuery Module]] contains functions to parse and serialize JSON documents. data [httphttps://www.json.org/ JSON (JavaScript Object Notation)] is a popular data exchange format for applications written in JavaScript. As there are notable differences between JSON and XML, or XQuery data types, no mapping exists that guarantees a lossless, bidirectional conversion between JSON and XML. For this reason, we offer two sets various mappings, all of functions in this module:which are suited to different use cases.
=Conventions=
All functions and errors in this module are assigned to the {{Code|<code><nowiki>http://basex.org/modules/json}} </nowiki></code> namespace, which is statically bound to the {{Code|json}} prefix.<br/>All errors are assigned to the {{Code|http://basex.org/errors}} namespace, which is statically bound to the {{Code|bxerr}} prefix.
==Conversion Formats==
==BaseX=='''A little advice''': in the Database Creation dialog of the GUI, if you select JSON Parsing and switch to the ''Parsing'' tab, you can see the effects of some of the conversion options.
The standard BaseX JSON format facilitates a lossless conversion from JSON to XML and back. The transformation is based on the following rules:# The resulting document has a {{Code|<json/>}} root node. # Names (keys) of objects are represented as elements:## Empty names are represented by a single underscore ({{Code|&lt;_&gt;...&lt;/_&gt;}}).## Underscore characters are rewritten to two underscores ({{Code|__}}).## A character that cannot be represented as NCName character is rewritten to an underscore and its four-digit Unicode.# As the members of arrays have no names, {{Code|&lt;value/&gt;}} is used as element name.# JSON values are represented as text nodes.# The types of values are represented in attributes:## The value types ''number'', ''boolean'', ''null'', ''object'' and ''array'' are represented by a {{Code|type}} attribute.## The ''string'' type is omitted, as it is treated as default type.## If a name has the same type throughout the document, the {{Code|type}} attribute will be omitted. Instead, the name will be listed in additional, type-specific attributes in the root node. The attributes are named by their type in the plural (''numbers'', ''booleans'', ''nulls'', ''objects'' and ''arrays''), and the attribute value contains all names with that type, separated by whitespaces.===Direct===
==JsonML==The {{Code|direct}} conversion format allows a lossless conversion from JSON to XML and back. The transformation is based on the following rules:
* The JsonML format can be resulting document has a {{Code|json}} root node. * Object pairs are represented via elements. The name of a pair is encoded, as described in the [[Conversion Module#Keys|Conversion Module]], and used to transform XML to JSON as element name.* Array entries are also represented via elements, with {{Code|_}} as element name.* Object and back, using the JsonML dialectarray values are stored in text nodes. JsonML allows the transformation * The types of arbitrary XML documentsvalues are represented via {{Code|type}} attributes:** The existing types are ''string'', but namespaces''number'', ''boolean'', ''null'', ''object'', comments and processing instructions will be discarded in the transformation process''array''. More details ** As most values are found in strings, the official [http://jsonml.org/XML JsonML documentation]''string'' type is by default omitted.
=Functions==Attributes=== The {{Code|attributes}} format is lossless, too. The transformation based on the following rules: * The resulting document has a {{Code|json}} root node. * Object pairs are represented via {{Code|pair}} elements. The name of a pair is stored in a {{Code|name}} attribute.* Array entries are represented via {{Code|item}} elements.* Object and array values are stored in text nodes.* The types of values are represented via {{Code|type}} attributes:** The existing types are ''string'', ''number'', ''boolean'', ''null'', ''object'', and ''array''.** As most values are strings, the ''string'' type is by default omitted. ===Basic=== The {{Code|basic}} format is another lossless format. It converts a JSON document to an XML node and vice versa. The conversion rules are the same as for [[XQuery 3.1#fn:json-to-xml|fn:json-to-xml]]. ===JsonML=== The {{Code|jsonml}} format is designed to convert XML to JSON and back, using the JsonML dialect. JsonML allows the transformation of arbitrary XML documents, but namespaces, comments and processing instructions will be discarded in the transformation process. More details are found in the official [http://jsonml.org/XML JsonML documentation]. ===XQuery=== The {{Code|xquery}} format is lossless, too. It converts JSON data to an XQuery value (a map, array, string, number, boolean, or empty sequence) and vice versa. The conversion rules are the same as for [[XQuery 3.1#fn:parse-json|fn:parse-json]]. The resulting representation consumes less memory than XML-based formats, and values can be directly accessed without conversion. Thus, it is recommendable for very large inputs and for efficient ad-hoc processing.
==json:parseOptions==
{{Version|7.7.2}}The following options are available (the ''Direction'' column indicates if an option applies to parsing, serialization, or both operations): {{Code|$options}} argument added
{| class="wikitable sortable" width='"100%'"|-valign="top"! width="140" | Option! width="50%" | Description! Allowed! Default! Direction|- valign="top"| {{Code|format}}| Specifies the format for converting JSON data.| {{Code|direct}}, {{Code|attributes}}, {{Code|jsonml}}, {{Code|xquery}}| {{Code|direct}}| '120' | parse'', 'Signatures'serialize''|- valign="top"|{{FuncCode|liberal}}|jsonDetermines if minor deviations from [https:parse//www.rfc-editor.org/rfc/rfc7159.txt RFC 7159] will be ignored.|$input as xs:string{{Code|element(json)yes}}<br/>, {{FuncCode|json:parseno}}|$input as xs:string, $options as item(){{Code|element(json)no}}|-| '''Summary'parse''|Converts the JSON document specified by - valign="top"| {{Code|merge}}| This option is considered when {{Code|$inputdirect}} to XML, and returns the result as or {{Code|element(json)attributes}} instance. The converted XML document conversion is both well readable and lossless, i.e., the converted document can be serialized back to the original JSON representation.used:<br/>The * If a name has the same type throughout the data, the {{Code|$optionstype}} argument can attribute will be used to control omitted. Instead, the way name will be listed in additional, type-specific attributes in the input is convertedroot node. * The following options attributes are available named by their type in plural (they bear resemblance to ''numbers'', ''booleans'', ''nulls'', ''objects'' and ''arrays''), and the ones specified in [http://wwwattribute value contains all names with that type, separated by whitespaces.w3.org/TR/xslt| {{Code|yes}}, {{Code|no}}| {{Code|no}}| ''parse'', ''serialize''|-30/#json XSLT 3.0]):valign="top"| {{Code|strings}}* | Indicates if {{Code|spectype}} determines the used JSON specificationattributes will be added for strings. Allowed values are | {{Code|RFC4627yes}}, {{Code|ECMA-262no}}| {{Code|yes}}| ''parse'', and ''serialize''|- valign="top"| {{Code|liberallax}}; the default | Specifies if a lax approach is (used to convert QNames to JSON names.| {{Code|RFC4627yes}}).* , {{Code|unescapeno}} determines whether escape sequences (marked by a backslash) in the input are expanded. The default is | {{Code|trueno}}.* | ''parse'', ''serialize''|- valign="top"| {{Code|formatescape}} determines the conversion format. Allowed values | Indicates if escaped characters are expanded (for example, {{Code|json\n}}, becomes a single {{Code|jsonmlx0A}}character, and while {{Code|map\u20AC}}; becomes the default is character {{Code|json}}).Options can either be specified<br />| {{Code|yes}}, {{Code|no}}* as children of an | {{Code|<json:options/>yes}} element; e.g.:<pre class| ''parse''|- valign="brush:xmltop"><json:options>| {{Code|escape}} <json:format value='jsonml'/> .| Indicates if characters are escaped whenever the JSON syntax requires it.This option can be set to {{Code|no}} if strings are already in escaped form and no further escaping is permitted.</json:options></pre>* or as map| {{Code|yes}}, which contains all key/value pairs:<pre class="brush:xquery">{ 'format' : 'jsonml', ... {Code|no}}</pre>|-{{Code|yes}}| '''Errors'serialize''|- valign="top"|{{ErrorCode|BXJS0001|#Errorsindent}} | Indicates if whitespace should be added to the output with the aim of improving human legibility. If the specified input cannot be parsed parameter is set as JSON documentin the query prolog, it overrides the {{Code|indent}} [[Serialization|serialization parameter]].<br/>| {{Code|yes}}, {{ErrorCode|no}}|BXJS0003{{Code|#Errorsyes}} a specified option cannot be parsed.| ''serialize''
|}
==json:serialize=Functions=
{{Version|7.7.2}}==json: {{Code|$options}} argument addedparse==
{| width='100%'
|-
| width='120' | '''Signatures'''
|{{Func|json:serializeparse|$input string as node()|xs:string?|item()?}}<br/>{{Func|json:serializeparse|$input string as node()xs:string?, $options as map(*)?|item()|xs:string?}}
|-
| '''Summary'''
|Serializes Converts the node specified by JSON {{Code|$input}} as JSON, and returns the result as {{Code|xs:string}} instanceto an XQuery value. The serialized node must conform to If the syntax specified by the [[#json:parse|json:parse()]] function.<br />XML documents input can be successfully parsed, it can also be serialized as back to the original JSON if the [[Serialization|Serialization Option]] {{Code|method}} is set to {{Code|json}}representation.<br/>The {{Code|$options}} argument can be used to control the way the input is serialized. The following options are available (they bear resemblance to the ones specified in [http://www.w3.org/TR/xslt-30/#json XSLT 3.0]):* {{Code|spec}} determines the used JSON specification. Allowed values are {{Code|RFC4627}}, {{Code|ECMA-262}}, and {{Code|liberal}}; the default is ({{Code|RFC4627}}).* {{Code|unescape}} determines whether escape sequences (marked by a backslash) in the input are expanded. The default is {{Code|true}}converted.* {{Code|format}} determines the conversion format. Allowed values are {{Code|json}}, {{Code|jsonml}}, and {{Code|map}}; the default is {{Code|json}}.Options can either be specified<br />* as children of an {{Code|<json:options/>}} element; e.g.:<pre class="brush:xml"><json:options> <json:format value='jsonml'/> ...</json:options></pre>* or as map, which contains all key/value pairs:<pre class="brush:xquery">{ 'format' : 'jsonml', ... }</pre>
|-
| '''Errors'''
|{{Error|BXJS0002parse|#Errors}} the specified node input cannot be serialized parsed as JSON document.<br/>{{Error|options|#Errors}} the specified options are conflicting.
|}
==json:serialize-mldoc==
{{VersionMark|7Introduced with BaseX 9.7.24:}}: deprecated; please use [[#json:serialize|json:serialize]] instead.
{| width='100%'
|-
| width='120' | '''Signatures'''
|{{Func|json:serialize-mldoc|$input uri as nodexs:string|item()?}}<br />{{Func|json:doc|$uri as xs:string, $options as map(*)?|item()?}}<br />
|-
| '''Summary'''
|Serializes Fetches the node specified JSON document referred to by the given {{Code|$inputuri}} and returns the result as converts it to an XQuery value. The {{Code|xs:string$options}} instance.<br />XML documents argument can also be output in used to control the JsonML format by setting way the [[Serialization|Serialization Option]] {{Code|"method"}} to {{Code|"jsonml"}}input is converted.
|-
| '''Errors'''
|{{Error|BXJS0002parse|#Errors}} the specified value input cannot be serializedparsed as JSON document.<br/>{{Error|options|#Errors}} the specified options are conflicting.
|}
==json:parse-mlserialize== {{Version|7.7.2}}: deprecated; please use [[#json:parse|json:parse]] instead.
{| width='100%'
|-
| width='120' | '''Signatures'''
|{{Func|json:parse-mlserialize|$input as item()?|xs:string}}<br/>{{Func|json:serialize|element$input as item()?, $options as map(*)?|xs:string}}
|-
| '''Summary'''
|Converts Serializes the [http://jsonml.org JsonML] document specified by {{Code|$input}} to XMLas JSON, using the specified {{Code|$options}}, and returns the result as string:* The input is expected to conform to the results that are created by [[#json:parse|json:parse()]].* Non-conforming items will be serialized as specified in the [[XQuery 3.1#JSON Serialization|json output method]] of the official recommendation.Values can also be serialized as JSON with the standard [[Serialization]] feature of XQuery:* The parameter {{Code|element()method}} instance. The JSON input must conform needs to be set to {{Code|json}}, and* the JsonML specification options presented in this article need to be successfully convertedassigned to the {{Code|json}} parameter.
|-
| '''Errors'''
|{{Error|BXJS0001serialize|#Errors}} the specified input node cannot be parsed serialized as JsonML instanceJSON document.
|}
'''Query:'''
<pre classsyntaxhighlight lang="brush:xquery">
let $database := "database"
for $name in file:list('.', false(), '*.json')
let $file := file:read-text($name)
let $json := json:parse($file)
return db:add($database, document { $json }, $name) </presyntaxhighlight>
'''Example 2: Converts a simple JSON string to XML and back'''
'''Query:'''
<pre classsyntaxhighlight lang="brush:xquery">
json:parse('{}')
</presyntaxhighlight>
'''Result:'''
<pre classsyntaxhighlight lang="brush:xml"><json objectstype="jsonobject"/></presyntaxhighlight>
'''Query:'''
<pre classsyntaxhighlight lang="brush:xquery">
(: serialize result as plain text :)
declare option output:method 'text';
json:serialize(<json objectstype="jsonobject"/>)</presyntaxhighlight>
'''Result:'''
<pre classsyntaxhighlight lang="brush:xquery">
{ }
</presyntaxhighlight>
'''Example 3: Converts a JSON string with simple objects and arrays'''
'''Query:'''
<pre classsyntaxhighlight lang="brush:xquery">
json:parse('{
"title": "Talk On Travel Pool",
"link": "http://www.flickr.com/groups/talkontravel/pool/",
"description": "Travel and vacation photos from around the world.",
"modified": "20092014-02-02T11:10:27Z",
"generator": "http://www.flickr.com/"
}')
</presyntaxhighlight>
'''Result:'''
<pre classsyntaxhighlight lang="brush:xml"><json objectstype="jsonobject">
<title>Talk On Travel Pool</title>
<link>http://www.flickr.com/groups/talkontravel/pool/</link>
<description>Travel and vacation photos from around the world.</description>
<modified>20092014-02-02T11:10:27Z</modified>
<generator>http://www.flickr.com/</generator>
</json>
</presyntaxhighlight>
'''Example 4: Converts a JSON string with different data types'''
'''Query:'''
<pre classsyntaxhighlight lang="brush:xquery">let $options := map { 'merge': true() }return json:parse('{
"first_name": "John",
"last_name": "Smith",
}
]
}', $options)</presyntaxhighlight>
'''Result:'''
<pre classsyntaxhighlight lang="brush:xml">
<json numbers="age code" arrays="phone" objects="json address value">
<first__name>John</first__name>
</address>
<phone>
<value_>
<type>home</type>
<number>212 555-1234</number>
</value_> <value_>
<type>mobile</type>
<number type="number">1327724623</number>
</value_>
</phone>
</json>
</presyntaxhighlight>
==JsonML Format==
'''Example 1: Converts all XML documents in a database to the JsonML format and writes them to disk'''
'''Query:'''
<pre classsyntaxhighlight lang="brush:xquery">
for $doc in collection('json')
let $name := document-uri($doc)
let $json := json:serialize($doc, map { 'format': 'jsonml' })
return file:write($name, $json)
</presyntaxhighlight>
'''Example 2: Converts a simple an XML fragment to the JsonML formatdocument with elements and text'''
'''Query:'''
<pre classsyntaxhighlight lang="brush:xquery">json:serialize(<xml/>, { 'format': 'jsonml' })</pre> '''Result:'''<pre>["xml"]</pre> '''Example 3: Converts an XML document with elements and text''' '''Query:'''<pre class="brush:xquery">json:serialize(doc('flickr.xml'), map { 'format': 'jsonml' })</presyntaxhighlight>
'''flickr.xml:'''
<pre classsyntaxhighlight lang="brush:xml">
<flickr>
<title>Talk On Travel Pool</title>
<link>http://www.flickr.com/groups/talkontravel/pool/</link>
<description>Travel and vacation photos from around the world.</description>
<modified>20092014-02-02T11:10:27Z</modified>
<generator>http://www.flickr.com/</generator>
</flickr>
</presyntaxhighlight>
'''Result:'''
<presyntaxhighlight lang="json">
["flickr",
["title",
"Talk On Travel Pool"],
["link",
"http:\/\/www.flickr.com\/groups\/talkontravel\/pool\/"],
["description",
"Travel and vacation photos from around the world."],
["modified",
"20092014-02-02T11:10:27Z"],
["generator",
"http:\/\/www.flickr.com\/"]]</presyntaxhighlight>
'''Example 43: Converts a document with nested elements and attributesto JsonML'''
'''Query:'''
<pre classsyntaxhighlight lang="brush:xquery">json:serialize(doc('input.xml'), map { 'format': 'jsonml' })</presyntaxhighlight>
'''input.xml:'''
<pre classsyntaxhighlight lang="brush:xml">
<address id='1'>
<!-- comments will be discarded -->
<phone type='home'>212 555-1234</phone>
</address>
</presyntaxhighlight>
'''Result:'''
<presyntaxhighlight lang="json">
["address", {"id":"1"},
["last_name",
["phone", {"type":"home"},
"212 555-1234"]]
</presyntaxhighlight> ==XQuery Format== '''Example 1: Converts a JSON string to XQuery''' '''Query:'''<syntaxhighlight lang="xquery">let $input := '{ "Title": "Drinks", "Author": [ "Jim Daniels", "Jack Beam" ]}'let $data := json:parse($input, map { 'format': 'xquery' })return map:for-each($data, function($k, $v) { $k || ': ' || string-join($v, ', ')})</syntaxhighlight> '''Result:'''<syntaxhighlight lang="json">Author: Jim Daniels, Jack BeamTitle: Drinks</syntaxhighlight> '''Example 2: Converts XQuery data to JSON''' '''Query:'''<syntaxhighlight lang="xquery">for $item in ( true(), 'ABC', array { 1 to 5 }, map { "Key": "Value" })return json:serialize( $item, map { 'format': 'xquery', 'indent': 'no' })</syntaxhighlight> '''Result:'''<syntaxhighlight lang="json">true"ABC"[1,2,3,4,5]{"Key":"Value"}</syntaxhighlight>
=Errors=
|Description
|-
|{{Code|BXJS0001options}}|The specified options are conflicting.|-|{{Code|parse}}
|The specified input cannot be parsed as JSON document.
|-
|{{Code|BXJS0002serialize}}
|The specified node cannot be serialized as JSON document.
|-
|{{Code|BXJS0003}}
|A specified option cannot be parsed.
|}
=Changelog=
 
;Version 9.4
* Added: [[#json:doc|json:doc]]
 
; Version 9.1
* Updated: [[#json:parse|json:parse]] can be called with empty sequence.
 
;Version 9.0
* Updated: <code>map</code> format renamed to <code>xquery</code>.
* Updated: error codes updated; errors now use the module namespace
 
;Version 8.4
* Updated: <code>unescape</code> changed to <code>escape</code>.
 
;Version 8.2
* Added: Conversion format <code>[[#Basic|basic]]</code>.
 
;Version 8.0
* Updated: Serialization aligned with the {{Code|json}} output method of the official specification.
* Added: {{Code|liberal}} option.
* Removed: {{Code|spec}} option.
 
;Version 7.8
* Removed: {{Code|json:parse-ml}}, {{Code|json:serialize-ml}}.
* Updated: {{Code|json:parse}} now returns a document node instead of an element, or an XQuery map if {{Code|format}} is set to {{Code|.map}}.
;Version 7.7.2
* Updated: {{Code|$options}} argument added to [[#json:parse|json:parse]] and [[#json:serialize|json:serialize]].* Updated: [[#json:parse-ml|json:parse-ml]] and [[#json:serialize-ml|json:serialize-ml]] are now ''deprecated''.
The module was introduced with Version 7.0.
 
[[Category:XQuery]]
Bureaucrats, editor, reviewer, Administrators
13,550

edits

Navigation menu