(:
: Copyright 2006-2009 The FLWOR Foundation.
:
: Licensed under the Apache License, Version 2.0 (the "License");
: you may not use this file except in compliance with the License.
: You may obtain a copy of the License at
:
: http://www.apache.org/licenses/LICENSE-2.0
:
: Unless required by applicable law or agreed to in writing, software
: distributed under the License is distributed on an "AS IS" BASIS,
: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
: See the License for the specific language governing permissions and
: limitations under the License.
:)
xquery version "3.0";
(:~
: Using this module, you can parse JSON data into XML, manipulate it like any
: other XML data using XQuery, and serialize the result back as JSON.
:
: There are many ways to represent JSON data in XML, some loss-less ("round
: tripable") and some lossy ("one way"). Loss-less representations preserve
: the JSON data types <i>boolean</i>, <i>number</i>, and <i>null</i>; lossy
: representations convert all data to strings.
: <p/>
: For a loss-less representation, Zorba implements that proposed by
: <a href="http://john.snelson.org.uk/parsing-json-into-xquery">John Snelson</a>.
: For example:
: <pre>
: {
: "firstName" : "John",
: "lastName" : "Smith",
: "address" : {
: "streetAddress" : "21 2nd Street",
: "city" : "New York",
: "state" : "NY",
: "postalCode" : 10021
: },
: "phoneNumbers" : [ "212 732-1234", "646 123-4567" ]
: }
: </pre>
: would be represented as:
: <pre>
: <json type="object">
: <pair name="firstName" type="string">John</pair>
: <pair name="lastName" type="string">Smith</pair>
: <pair name="address" type="object">
: <pair name="streetAddress" type="string">21 2nd Street</pair>
: <pair name="city" type="string">New York</pair>
: <pair name="state" type="string">NY</pair>
: <pair name="postalCode" type="number">10021</pair>
: </pair>
: <pair name="phoneNumbers" type="array">
: <item type="string">212 732-1234</item>
: <item type="string">646 123-4567</item>
: </pair>
: </json>
: </pre>
: For a lossy representation, Zorba implements
: <a href="http://jsonml.org/">JsonML</a> (the array form).
: For example:
: <pre>
: [ "person",
: { "created" : "2006-11-11T19:23",
: "modified" : "2006-12-31T23:59" },
: [ "firstName", "Robert" ],
: [ "lastName", "Smith" ],
: [ "address",
: { "type" : "home" },
: [ "street", "12345 Sixth Ave" ],
: [ "city", "Anytown" ],
: [ "state", "CA" ],
: [ "postalCode", "98765-4321" ]
: ]
: ]
: </pre>
: would be represented as:
: <pre>
: <person created="2006-11-11T19:23" modified="2006-12-31T23:59">
: <firstName>Robert</firstName>
: <lastName>Smith</lastName>
: <address type="home">
: <street>12345 Sixth Ave</street>
: <city>Anytown</city>
: <state>CA</state>
: <postalCode>98765-4321</postalCode>
: </address>
: </person>
: </pre>
:
: @author Paul J. Lucas
: @project data processing/data converters
:)
module namespace json = "http://www.zorba-xquery.com/modules/converters/json";
import module namespace schema = "http://www.zorba-xquery.com/modules/schema";
import schema namespace json-options =
"http://www.zorba-xquery.com/modules/converters/json-options";
declare namespace an = "http://www.zorba-xquery.com/annotations";
declare namespace err = "http://www.w3.org/2005/xqt-errors";
declare namespace zerr = "http://www.zorba-xquery.com/errors";
declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
declare option ver:module-version "2.0";
(:~
: Parses JSON data from a string and returns an XDM instance using one of the
: representations described above.
:
: @param $json The JSON data to parse.
: @param $options The parsing options, for example:
: <pre>
: <options xmlns="http://www.zorba-xquery.com/modules/converters/json-options">
: <json-format value="JsonML-array"/>
: </options>
: </pre>
: @return said XDM instance.
: @error err:XQDY0027 if $options can not be validated against the
: json-options schema.
: @error zerr:ZJPE0001 if $json contains an illegal JSON character.
: @error zerr:ZJPE0002 if $json contains an illegal Unicode code-point.
: @error zerr:ZJPE0003 if $json contains an illegal JSON character escape.
: @error zerr:ZJPE0004 if $json contains an illegal JSON literal.
: @error zerr:ZJPE0005 if $json contains an illegal JSON number.
: @error zerr:ZJPE0006 if $json is not a valid JSON string.
: @error zerr:ZJPE0007 if $json contains an unterminated string.
: @error zerr:ZJPE0008 if $json contains an illegal QName.
: @example test/rbkt/Queries/zorba/json/json-jsonml_array-parse-01.xq
:)
declare function json:parse(
$json as xs:string?,
$options as element(json-options:options)
) as element(*,xs:untyped)*
{
let $validated-options := if ( schema:is-validated( $options ) ) then
$options
else
validate { $options }
return json:parse-internal( $json, $validated-options )
};
(:~
: Parses JSON data from a string and returns an XDM instance using the Snelson
: representation described above.
:
: @param $json The JSON data to parse.
: @return said XDM instance.
: @error zerr:ZJPE0001 if $json contains an illegal JSON character.
: @error zerr:ZJPE0002 if $json contains an illegal Unicode code-point.
: @error zerr:ZJPE0003 if $json contains an illegal JSON character escape.
: @error zerr:ZJPE0004 if $json contains an illegal JSON literal.
: @error zerr:ZJPE0005 if $json contains an illegal JSON number.
: @error zerr:ZJPE0006 if $json is not a valid JSON string.
: @error zerr:ZJPE0007 if $json contains an unterminated string.
: @error zerr:ZJPE0008 if $json contains an illegal QName.
: @example test/rbkt/Queries/zorba/json/json-snelson-parse-array-01.xq
:)
declare function json:parse(
$json as xs:string?
) as element(*,xs:untyped)*
{
json:parse-internal(
$json,
validate {
<options
xmlns="http://www.zorba-xquery.com/modules/converters/json-options">
<json-format value="Snelson"/>
</options>
}
)
};
(:~
: Serializes an XDM into JSON using one of the representations described
: above.
:
: @param $xml The XDM to serialize.
: @param $options The serializing options, for example:
: <pre>
: <options xmlns="http://www.zorba-xquery.com/modules/converters/json-options">
: <json-format value="JsonML-array"/>
: <whitespace value="indent"/>
: </options>
: </pre>
: @return a JSON string.
: @error err:XQDY0027 if $options can not be validated against the
: json-options schema.
: @error zerr:ZJSE0001 if $xml is not a document or element node.
: @error zerr:ZJSE0002 if $xml contains an element that is missing a required
: attribute.
: @error zerr:ZJSE0003 if $xml contains an attribute having an illegal value.
: @error zerr:ZJSE0004 if $xml contains an illegal element.
: @error zerr:ZJSE0005 if $xml contains an illegal child element for a JSON
: type.
: @error zerr:ZJSE0006 if $xml contains an illegal child element.
: @error zerr:ZJSE0007 if $xml contains an illegal text node.
: @error zerr:ZJSE0008 if $xml contains an illegal value for a JSON type.
: @example test/rbkt/Queries/zorba/json/json-jsonml_array-serialize-01.xq
:)
declare function json:serialize(
$xml as item()*,
$options as element(json-options:options)
) as xs:string
{
let $validated-options := if ( schema:is-validated( $options ) ) then
$options
else
validate { $options }
return json:serialize-internal( $xml, $validated-options )
};
(:~
: Serializes an XDM into JSON using one of the representations described
: above.
:
: @param $xml The XDM to serialize.
: @return a JSON string.
: @error zerr:ZJSE0001 if $xml is not a document or element node.
: @error zerr:ZJSE0002 if $xml contains an element that is missing a required
: attribute.
: @error zerr:ZJSE0003 if $xml contains an attribute having an illegal value.
: @error zerr:ZJSE0004 if $xml contains an illegal element.
: @error zerr:ZJSE0005 if $xml contains an illegal child element for a JSON
: type.
: @error zerr:ZJSE0006 if $xml contains an illegal child element.
: @error zerr:ZJSE0007 if $xml contains an illegal text node.
: @error zerr:ZJSE0008 if $xml contains an illegal value for a JSON type.
: @example test/rbkt/Queries/zorba/json/json-snelson-serialize-array-01.xq
:)
declare function json:serialize(
$xml as item()*
) as xs:string
{
json:serialize-internal($xml,
validate {
<options
xmlns="http://www.zorba-xquery.com/modules/converters/json-options">
<json-format value="Snelson"/>
</options>
}
)
};
(:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare %private function json:parse-internal(
$json as xs:string?,
$options as item()?
) as element()* external;
declare %an:streamable %private function json:serialize-internal(
$xml as item()*,
$options as item()?
) as xs:string external;
(: vim:set et sw=2 ts=2: :)