This [[Module Library|XQuery Module]] contains functions to parse and serialize JSON 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 various mappings, all of which are suited to different use cases.
=Conventions=
The {{Code|direct}} conversion format allows 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. * Object pairs are represented via elements. The name of a pair is rewritten to an element name:** Empty names are represented by a single underscore ({{Code|_}}). Existing underscores are rewritten to two underscores ({{Code|__}})encoded, and characters that are not valid as described in element names are rewritten to an underscore and the character’s four-digit Unicode.** If the {{Code[[Conversion Module#Keys|lax}} option is set to {{Code|true}}Conversion Module]], invalid characters are simply replaced with underscores or (when invalid and used as first character of an element name) prefixed with an underscore. The resulting names are better readable, but cannot always be converted back to their original form.* Array entries are also represented via elements. , with {{Code|_}} is used as element name.
* Object and array values are stored in text nodes.
* The types of values are represented via {{Code|type}} 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:
|- valign="top"
| {{Code|format}}
| Specifies the format for converting JSON data([[#Conversion Formats|see above]]).| {{Code|direct}}, {{Code|attributes}}, {{Code|basic}}, {{Code|jsonml}}, {{Code|xquery}}
| {{Code|direct}}
| ''parse'', ''serialize''
|- valign="top"
| {{Code|liberal}}
| Determines if minor deviations from [httphttps://www.rfc-editor.org/rfc/rfc7159.txt RFC 7159] will be ignored.
| {{Code|yes}}, {{Code|no}}
| {{Code|no}}
|- valign="top"
| {{Code|lax}}
| Specifies if a [[Conversion Module#Keys|lax approach is conversion rules]] are used to convert QNames to JSON names.
| {{Code|yes}}, {{Code|no}}
| {{Code|no}}
| Indicates if whitespace should be added to the output with the aim of improving human legibility. If the parameter is set as in the query prolog, it overrides the {{Code|indent}} [[Serialization|serialization parameter]].
| {{Code|yes}}, {{Code|no}}
| {{Code|yesno}}
| ''serialize''
|}
=Functions=
==json:doc==
{| width='100%'
|- valign="top"
| width='120' | '''Signature'''
|<pre>json:doc(
$href as xs:string,
$options as map(*)? := map { }
) as item()?</pre>
|- valign="top"
| '''Summary'''
|Fetches the JSON document referred to by the given {{Code|$href}} and converts it to an XQuery value. The {{Code|$options}} argument can be used to control the way the input is converted.
|- valign="top"
| '''Errors'''
|{{Error|parse|#Errors}} the specified input cannot be parsed as JSON document.<br/>{{Error|options|#Errors}} the specified options are conflicting.
|}
==json:parse==
{| width='100%'
|-valign="top"| width='120' | '''SignaturesSignature'''|{{Func|json:parse|$string as xs:string?|item()?}}<br/pre>{{Func|json:parse|( $string value as xs:string?, $options as map(*)?| := map { }) as item()?}}</pre>|-valign="top"
| '''Summary'''
|Converts the JSON {{Code|$stringvalue}} to an XQuery value. If the input can be successfully parsed, it can be serialized back to the original JSON representation. The {{Code|$options}} argument can be used to control the way the input is converted.|-valign="top"
| '''Errors'''
|{{Error|parse|#Errors}} the specified input cannot be parsed as JSON document.<br/>{{Error|options|#Errors}} the specified options are conflicting.
{| width='100%'
|-valign="top"| width='120' | '''SignaturesSignature'''|{{Func|json:serialize|$input as item()?|xs:string}}<br/pre>{{Func|json:serialize|( $input as item()?, $options as map(*)?| := map { }) as xs:string}}</pre>|-valign="top"
| '''Summary'''
|Serializes the specified {{Code|$input}} as 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{{Function||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|method}} needs to be set to {{Code|json}}, and
* the options presented in this article need to be assigned to the {{Code|json}} parameter.
|-valign="top"
| '''Errors'''
|{{Error|serialize|#Errors}} the specified node cannot be serialized as JSON document.
'''Query:'''
<pre classlang="brush:'xquery"'>
let $database := "database"
for $name in file:list('.', false(), '*.json')
'''Query:'''
<pre classlang="brush:'xquery"'>
json:parse('{}')
</pre>
'''Result:'''
<pre classlang="brush:xml">
<json type="object"/>
</pre>
'''Query:'''
<pre classlang="brush:'xquery"'>
(: serialize result as plain text :)
declare option output:method 'text';
'''Result:'''
<pre classlang="brush:'xquery"'>
{ }
</pre>
'''Query:'''
<pre classlang="brush:'xquery"'>
json:parse('{
"title": "Talk On Travel Pool",
'''Result:'''
<pre classlang="brush:xml">
<json type="object">
<title>Talk On Travel Pool</title>
'''Query:'''
<pre classlang="brush:'xquery"'>
let $options := map { 'merge': true() }
return json:parse('{
'''Result:'''
<pre classlang="brush:xml">
<json numbers="age code" arrays="phone" objects="json address value">
<first__name>John</first__name>
'''Query:'''
<pre classlang="brush:'xquery"'>
for $doc in collection('json')
let $name := document-uri($doc)
'''Query:'''
<pre classlang="brush:'xquery"'>
json:serialize(doc('flickr.xml'), map { 'format': 'jsonml' })
</pre>
'''flickr.xml:'''
<pre classlang="brush:xml">
<flickr>
<title>Talk On Travel Pool</title>
'''Result:'''
<prelang="json">
["flickr",
["title",
'''Query:'''
<pre classlang="brush:'xquery"'>
json:serialize(doc('input.xml'), map { 'format': 'jsonml' })
</pre>
'''input.xml:'''
<pre classlang="brush:xml">
<address id='1'>
<!-- comments will be discarded -->
'''Result:'''
<prelang="json">
["address", {"id":"1"},
["last_name",
'''Query:'''
<pre classlang="brush:'xquery"'>
let $input := '{
"Title": "Drinks",
'''Result:'''
<prelang="json">
Author: Jim Daniels, Jack Beam
Title: Drinks
'''Query:'''
<pre classlang="brush:'xquery"'>
for $item in (
true(),
'''Result:'''
<prelang="json">
true
"ABC"
! width="110"|Code
|Description
|-valign="top"
|{{Code|options}}
|The specified options are conflicting.
|-valign="top"
|{{Code|parse}}
|The specified input cannot be parsed as JSON document.
|-valign="top"
|{{Code|serialize}}
|The specified node cannot be serialized as JSON document.
=Changelog=
;Version 10.0
* Updated: {{Code|indent}}: Default changed from {{Code|yes}} to {{Code|no}}.
;Version 9.4
* Added: {{Function||json:doc}}
; Version 9.1
* Updated: [[#json:parse{{Function||json:parse]] }} can be called with empty sequence.
;Version 9.0
;Version 7.7.2
* Updated: {{Code|$options}} argument added to [[#json:parse{{Function||json:parse]] }} and [[#json:serialize{{Function||json:serialize]]}}.* Updated: [[#json:parse-ml{{Function||json:parse-ml]] }} and [[#json:serialize-ml{{Function||json:serialize-ml]] }} are now ''deprecated''.
The module was introduced with Version 7.0.