JSON Module
This XQuery Module contains functions to parse and serialize JSON documents. JSON (JavaScript Object Notation) is a popular data exchange format for applications written in JavaScript. As there are notable differences between JSON and XML, 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.
Contents
Conventions
All functions in this module are assigned to the http://basex.org/modules/json
namespace, which is statically bound to the json
prefix.
All errors are assigned to the http://basex.org/errors
namespace, which is statically bound to the bxerr
prefix.
Conversion Formats
The JSON conversion rules have been updated with Version 7.8:
Direct
The 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
<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 (
_
), existing underscores are rewritten to two underscores (__
), and characters that are not valid in element names are rewritten to an underscore and the character’s four-digit Unicode. - If the
lax
option is set tofalse
, invalid characters are simply replaced with underscores. The resulting names are better readable, but may not be losslessly converted back to their original form.
- Empty names are represented by a single underscore (
- Array entries are also represented via elements.
<_>
is used as element name (value
was used before Version 7.8). - Object and array values are stored in text nodes.
- The types of values are represented via
type
attributes:- The existing types are string, number, boolean, null, object, and array.
- As string is the default, it is by default omitted.
Attributes
The attributes
format is lossless, too. The transformation based on the following rules:
- The resulting document has a
<json>
root node. - Object pairs are represented via
<pair>
elements. The name of a pair is stored in aname
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
type
attributes:- The existing types are string, number, boolean, null, object, and array.
- As string is the default, it is by default omitted.
Map
The map
format is lossless. The conversion rules for are specified in the [XSLT 3.0|http://www.w3.org/TR/xslt-30/#func-parse-json specification].
JsonML
The jsonml
format can be used to transform 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 JsonML documentation.
Options
The following options are available:
Option | Description | Allowed | Default | Direction |
---|---|---|---|---|
format
|
Specifies the format for converting JSON data. | direct , attributes , jsonml , map
|
direct
|
parse, serialize |
spec
|
Determines the specification that is used for parsing JSON data:
|
RFC4627 , ECMA-262 , liberal
|
liberal
|
parse, serialize |
merge
|
This option is considered when direct or attributes conversion is used:
|
yes , no
|
no
|
parse, serialize |
strings
|
Indicates if type attributes will be added for strings.
|
yes , no
|
yes
|
parse, serialize |
lax
|
Specifies if a lax approach is used to convert QNames to JSON names. | yes , no
|
yes
|
parse, serialize |
unescape
|
Indicates if escaped characters are expanded (for example, \n becomes a single x0A character, while \u20AC becomes the character € ).
|
yes , no
|
yes
|
parse |
escape
|
Indicates if characters are escaped whenever the JSON syntax requires it. This option can be set to no if strings are already in escaped form and no further escaping is permitted.
|
yes , no
|
yes
|
serialize |
indent
|
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 indent serialization parameter.
|
yes , no
|
yes
|
serialize |
The JSON function signatures provide an $options
argument. Options can either be specified
- as children of an
<json:options/>
element; e.g.:
<json:options> <json:separator value=';'/> ... </json:options>
- or as map, which contains all key/value pairs:
{ 'separator': ';', ... }
Functions
json:parse
Version 7.7.2: $options
argument added
Signatures | json:parse($input as xs:string) as element(json) json:parse($input as xs:string, $options as item()) as element(json)
|
Summary | Converts the JSON document specified by $input to XML, and returns the result as element(json) instance. The converted XML document is both well readable and lossless, i.e., the converted document can be serialized back to the original JSON representation. The $options argument can be used to control the way the input is converted.
|
Errors | BXJS0001 : the specified input cannot be parsed as JSON document.
|
json:serialize
Version 7.7.2: $options
argument added
Signatures | json:serialize($input as node()) as xs:string json:serialize($input as node(), $options as item()) as xs:string
|
Summary | Serializes the node specified by $input as JSON, and returns the result as xs:string instance. The serialized node must conform to the syntax specified by the json:parse() function.XML documents can also be serialized as JSON if the Serialization Option method is set to json .The $options argument can be used to control the way the input is serialized.
|
Errors | BXJS0002 : the specified node cannot be serialized as JSON document.
|
Examples
BaseX Format
Example 1: Adds all JSON documents in a directory to a database
Query:
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)
Example 2: Converts a simple JSON string to XML and back
Query:
json:parse('{}')
Result:
<json objects="json"/>
Query:
(: serialize result as plain text :) declare option output:method 'text'; json:serialize(<json objects="json"/>)
Result:
{ }
Example 3: Converts a JSON string with simple objects and arrays
Query:
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": "2009-02-02T11:10:27Z", "generator": "http://www.flickr.com/" }')
Result:
<json objects="json"> <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>2009-02-02T11:10:27Z</modified> <generator>http://www.flickr.com/</generator> </json>
Example 4: Converts a JSON string with different data types
Query:
json:parse('{ "first_name": "John", "last_name": "Smith", "age": 25, "address": { "street": "21 2nd Street", "city": "New York", "code": 10021 }, "phone": [ { "type": "home", "number": "212 555-1234" }, { "type": "mobile", "number": 1327724623 } ] }')
Result:
<json numbers="age code" arrays="phone" objects="json address value"> <first__name>John</first__name> <last__name>Smith</last__name> <age>25</age> <address> <street>21 2nd Street</street> <city>New York</city> <code>10021</code> </address> <phone> <value> <type>home</type> <number>212 555-1234</number> </value> <value> <type>mobile</type> <number type="number">1327724623</number> </value> </phone> </json>
JsonML Format
Example 1: Converts all XML documents in a database to JsonML and writes them to disk
Query:
for $doc in collection('json') let $name := document-uri($doc) let $json := json:serialize($doc) return file:write($name, $json)
Example 2: Converts a simple XML fragment to the JsonML format
Query:
json:serialize(<xml/>, { 'format': 'jsonml' })
Result:
["xml"]
Example 3: Converts an XML document with elements and text
Query:
json:serialize(doc('flickr.xml'), { 'format': 'jsonml' })
flickr.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>2009-02-02T11:10:27Z</modified> <generator>http://www.flickr.com/</generator> </flickr>
Result:
["flickr", ["title", "Talk On Travel Pool"], ["link", "http:\/\/www.flickr.com\/groups\/talkontravel\/pool\/"], ["description", "Travel and vacation photos from around the world."], ["modified", "2009-02-02T11:10:27Z"], ["generator", "http:\/\/www.flickr.com\/"]]
Example 4: Converts a document with nested elements and attributes
Query:
json:serialize(doc('input.xml'), { 'format': 'jsonml' })
input.xml:
<address id='1'> <!-- comments will be discarded --> <last_name>Smith</last_name> <age>25</age> <address xmlns='will be dropped as well'> <street>21 2nd Street</street> <city>New York</city> <code>10021</code> </address> <phone type='home'>212 555-1234</phone> </address>
Result:
["address", {"id":"1"}, ["last_name", "Smith"], ["age", "25"], ["address", ["street", "21 2nd Street"], ["city", "New York"], ["code", "10021"]], ["phone", {"type":"home"}, "212 555-1234"]]
Errors
Code | Description |
---|---|
BXJS0001
|
The specified input cannot be parsed as JSON document. |
BXJS0002
|
The specified node cannot be serialized as JSON document. |
Changelog
- Version 7.8
- Removed:
json:parse-ml
,json:serialize-ml
- Version 7.7.2
- Updated:
$options
argument added to json:parse and json:serialize - Updated: json:parse-ml and json:serialize-ml are now deprecated
The module was introduced with Version 7.0.