zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #13350
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
Ghislain Fourny has proposed merging lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba.
Requested reviews:
William Candillon (wcandillon)
Matthias Brantner (matthias-brantner)
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/updated-jsoniq-tutorials/+merge/120388
Updated JSONiq tutorial.
--
https://code.launchpad.net/~zorba-coders/zorba/updated-jsoniq-tutorials/+merge/120388
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'doc/zorba/JSONforXQuery.html'
--- doc/zorba/JSONforXQuery.html 2012-07-25 13:42:21 +0000
+++ doc/zorba/JSONforXQuery.html 2012-08-20 13:39:02 +0000
@@ -1,1 +1,1 @@
-<html><head><title>JSON for XQuery</title><style type="text/css">@import url('https://themes.googleusercontent.com/fonts/css?kit=lhDjYqiy3mZ0x6ROQEUoUw');ol{margin:0;padding:0}.c22{max-width:468pt;background-color:#ffffff;padding:72pt 72pt 72pt 72pt}.c7{padding-left:0pt;text-align:justify;margin-left:36pt}.c17{list-style-type:disc;margin:0;padding:0}.c23{text-indent:-13pt;margin-left:77pt}.c5{color:#1155cc;text-decoration:underline}.c13{color:inherit;text-decoration:inherit}.c18{font-weight:bold}.c6{margin-left:18pt}.c15{text-indent:139.5pt}.c8{color:#38761d}.c16{color:#4a86e8}.c14{font-style:italic}.c2{text-align:right}.c9{text-align:justify}.c4{margin-left:144pt}.c19{margin-left:36pt}.c11{text-indent:156pt}.c3{height:11pt}.c0{font-family:"Consolas"}.c1{direction:ltr}.c20{text-align:center}.c12{margin-left:49.5pt}.c21{height:18pt}.c10{text-indent:144pt}.title{padding-top:24pt;line-height:1.15;text-align:center;color:#4a86e8;font-size:36pt;font-family:"Arial";font-weight:bold;padding-bottom:6pt}.subtitle{padding-top:18pt;line-height:1.15;text-align:left;color:#666666;font-style:italic;font-size:24pt;font-family:"Georgia";padding-bottom:4pt}li{color:#000000;font-size:11pt;font-family:"Arial"}p{color:#000000;font-size:11pt;margin:0;font-family:"Arial"}h1{padding-top:24pt;line-height:1.15;text-align:left;color:#4a86e8;font-size:24pt;font-family:"Arial";font-weight:bold;padding-bottom:6pt}h2{padding-top:18pt;line-height:1.15;text-align:left;color:#ff9900;font-size:18pt;font-family:"Arial";font-weight:bold;padding-bottom:4pt}h3{padding-top:14pt;line-height:1.15;text-align:left;color:#000000;font-size:14pt;font-family:"Arial";font-weight:bold;padding-bottom:4pt}h4{padding-top:12pt;line-height:1.15;text-align:left;color:#000000;font-size:12pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}h5{padding-top:11pt;line-height:1.15;text-align:left;color:#000000;font-size:11pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}h6{padding-top:10pt;line-height:1.15;text-align:left;color:#000000;font-size:10pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}</style></head><body class="c22"><p class="c1 title"><a name="h.li2wdq8unbq"></a><span>JSONiq for XQuery users</span></p><p class="c1 title"><a name="h.5ipqqclfxk4n"></a><span class="c8">JSON for XQuery</span></p><hr><p class="c1 c20"><span>This tutorial introduces the JSONiq language, which declaratively manipulates JSON data.</span></p><p class="c1 c20"><span>Why don't you go ahead can try the queries of this document on our online demo interface?</span></p><p class="c1 c20"><span> </span><span class="c5 c18"><a class="c13" href="http://jsoniq.zorba-xquery.com/">http://jsoniq.zorba-xquery.com/</a></span></p><hr><p class="c3 c1"><span></span></p><h2 class="c1 c21"><a name="h.8gra0ylxutrv"></a></h2><p class="c6 c1"><span class="c5"><a class="c13" href="#h.f453h84m2u1a">JSON</a></span></p><p class="c6 c1"><span class="c5"><a class="c13" href="#h.qtfakecy3fr7">Elevator Pitch</a></span></p><p class="c6 c1"><span class="c5"><a class="c13" href="#h.yugk1mszt0re">And here you go</a></span></p><p class="c19 c1"><span class="c5"><a class="c13" href="#h.39rm37noeh9g">JSONiq types</a></span></p><p class="c1 c19"><span class="c5"><a class="c13" href="#h.j0wg8654ivtw">JSON Constructors</a></span></p><p class="c19 c1"><span class="c5"><a class="c13" href="#h.qe57mgdf5ql">JSON as a subset of JSONiq</a></span></p><p class="c1 c6"><span class="c5"><a class="c13" href="#h.dewn8sw3husv">JSON Navigation</a></span></p><p class="c19 c1"><span class="c5"><a class="c13" href="#h.zcnazhl6374z">Objects</a></span></p><p class="c19 c1"><span class="c5"><a class="c13" href="#h.30wafxvenhgy">Arrays</a></span></p><p class="c6 c1"><span class="c5"><a class="c13" href="#h.eb0bxle2oykl">Relational Algebra</a></span></p><p class="c6 c1"><span class="c5"><a class="c13" href="#h.oii6pvliilhi">Access external data</a></span></p><p class="c6 c1"><span class="c5"><a class="c13" href="#h.fopcxnkoydgt">JSON and XML</a></span></p><p class="c6 c1"><span class="c5"><a class="c13" href="#h.bm3buqmzhtko">I want more</a></span></p><p class="c3 c1"><span></span></p><h1 class="c1"><a name="h.f453h84m2u1a"></a><span>JSON</span></h1><p class="c9 c1"><span>As explained on </span><span class="c5"><a class="c13" href="http://www.json.org/">http://www.json.org/</a></span><span>, JSON is a lightweight data-interchange format designed for humans as well as for computers. It supports as values:</span></p><ol class="c17" start="1"><li class="c7 c1"><span>objects (string-to-value map)</span></li><li class="c7 c1"><span>arrays (ordered sequence of values)</span></li><li class="c7 c1"><span>strings</span></li><li class="c7 c1"><span>numbers</span></li><li class="c7 c1"><span>booleans (true, false)</span></li><li class="c7 c1"><span>null</span></li></ol><p class="c3 c1"><span></span></p><p class="c1"><span>JSONiq extends XQuery to query and update JSON data, like XML data.</span></p><h1 class="c1"><a name="h.qtfakecy3fr7"></a><span>Elevator Pitch</span></h1><p class="c9 c1"><span>Here is an appetizer before we start the tutorial from scratch.</span></p><p class="c3 c1"><span></span></p><p class="c1"><span class="c0">let $stores :=</span></p><p class="c1"><span class="c0">[</span></p><p class="c1"><span class="c0"> { "store number" : 1, "state" : "MA" },</span></p><p class="c1"><span class="c0"> { "store number" : 2, "state" : "MA" },</span></p><p class="c1"><span class="c0"> { "store number" : 3, "state" : "CA" },</span></p><p class="c1"><span class="c0"> { "store number" : 4, "state" : "CA" }</span></p><p class="c1"><span class="c0">]</span></p><p class="c1"><span class="c0">let $sales := [</span></p><p class="c1"><span class="c0"> { "product" : "broiler", "store number" : 1, "quantity" : 20 },</span></p><p class="c1"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 100 },</span></p><p class="c1"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 50 },</span></p><p class="c1"><span class="c0"> { "product" : "toaster", "store number" : 3, "quantity" : 50 },</span></p><p class="c1"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 100 },</span></p><p class="c1"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 150 },</span></p><p class="c1"><span class="c0"> { "product" : "socks", "store number" : 1, "quantity" : 500 },</span></p><p class="c1"><span class="c0"> { "product" : "socks", "store number" : 2, "quantity" : 10 },</span></p><p class="c1"><span class="c0"> { "product" : "shirt", "store number" : 3, "quantity" : 10 }</span></p><p class="c1"><span class="c0">]</span></p><p class="c1"><span class="c0">let $join :=</span></p><p class="c1"><span class="c0"> for $store in jn:members($stores), $sale in jn:members($sales)</span></p><p class="c1"><span class="c0"> where $store("store number") = $sale("store number")</span></p><p class="c1"><span class="c0"> return {</span></p><p class="c1"><span class="c0"> "nb" : $store("store number"),</span></p><p class="c1"><span class="c0"> "state" : $store("state"),</span></p><p class="c1"><span class="c0"> "sold" : $sale("product")</span></p><p class="c1"><span class="c0"> }</span></p><p class="c1"><span class="c0">return [$join]</span></p><p class="c4 c1"><span class="c8 c0">[ </span></p><p class="c4 c1"><span class="c8 c0"> { "nb" : 1, "state" : "MA", "sold" : "broiler" },</span></p><p class="c4 c1"><span class="c8 c0"> { "nb" : 1, "state" : "MA", "sold" : "socks" },</span></p><p class="c4 c1"><span class="c8 c0"> { "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c4 c1"><span class="c0 c8"> { "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c4 c1"><span class="c8 c0"> { "nb" : 2, "state" : "MA", "sold" : "socks" },</span></p><p class="c4 c1"><span class="c8 c0"> { "nb" : 3, "state" : "CA", "sold" : "toaster" },</span></p><p class="c4 c1"><span class="c8 c0"> { "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c4 c1"><span class="c8 c0"> { "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c4 c1"><span class="c8 c0"> { "nb" : 3, "state" : "CA", "sold" : "shirt" }</span></p><p class="c4 c1"><span class="c8 c0"> ]</span></p><p class="c3 c1"><span></span></p><h1 class="c1"><a name="h.yugk1mszt0re"></a><span>And here you go</span></h1><h2 class="c1"><a name="h.39rm37noeh9g"></a><span>JSONiq types</span></h2><p class="c1"><span>JSONiq maps JSON types to XQuery. Numbers are xs:integer or xs:decimal, strings are xs:string, true and false are xs:boolean and null is a new atomic type jn:null.</span></p><p class="c3 c1"><span></span></p><p class="c1"><span>By default, in JSONiq, for convenience, true, false and null are recognized as literals instead of name tests. However, this can be deactivated.</span></p><p class="c3 c1"><span></span></p><p class="c1"><span>JSONiq introduces new items: objects and arrays. Objects are sets of key/value pairs. Array have members which are values. Values are objects, arrays, XML nodes, functions or atomic items.</span></p><p class="c3 c1"><span></span></p><p class="c1"><span>The new item types for objects and arrays are object() and array(). json-item() is a supertype of both. structured-item() is a supertype for json-item() and node().</span></p><h2 class="c1"><a name="h.j0wg8654ivtw"></a><span>JSON Constructors</span></h2><p class="c1"><span>JSONiq introduces JSON constructors, in a similar way to XML constructors.</span></p><p class="c3 c1"><span></span></p><p class="c1"><span>You can put any expression in a array. The items in the sequence produced by the expression will become members of the array:</span></p><p class="c3 c1"><span></span></p><p class="c1"><span class="c0">[ 1 to 10 ]</span></p><p class="c2 c1"><span class="c8 c0">[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]</span></p><p class="c2 c3 c1"><span class="c8 c0"></span></p><p class="c1"><span>Or you can dynamically compute an object:</span></p><p class="c3 c1"><span></span></p><p class="c1"><span class="c0">{</span></p><p class="c1"><span class="c0"> "Greeting" : (let $d := "Mister Spock"</span></p><p class="c1"><span class="c0"> return concat("Hello, ", $d)),</span></p><p class="c1"><span class="c0"> "Farewell" : string-join(("Live", "long", "and", "prosper"),</span></p><p class="c1"><span class="c0"> " ")</span></p><p class="c1"><span class="c0">}</span></p><p class="c3 c1"><span class="c8 c0"></span></p><p class="c2 c1"><span class="c8 c0">{ "Greeting" : "Hello, Mister Spock", "Farewell" : "Live long and prosper" }</span></p><p class="c3 c1"><span class="c8"></span></p><p class="c1"><span>You can also dynamically generate singleton objects:</span></p><p class="c3 c1"><span class="c0"></span></p><p class="c1"><span class="c0">{ concat("Integer ", 2) : 2 * 2 }</span></p><p class="c2 c1"><span class="c8 c0">{ "Integer 2" : 4 }</span></p><p class="c2 c3 c1"><span class="c8 c0"></span></p><p class="c1"><span>and then wrap lots of them in an object:</span></p><p class="c3 c1"><span class="c0"></span></p><p class="c1"><span class="c0">{|</span></p><p class="c1"><span class="c0"> for $i in 1 to 10</span></p><p class="c1"><span class="c0"> return { concat("Square of ", $i) : $i * $i }</span></p><p class="c1"><span class="c0">|}</span></p><p class="c4 c1"><span class="c8 c0">{</span></p><p class="c4 c1"><span class="c8 c0">"Square of 1" : 1,</span></p><p class="c1 c4"><span class="c8 c0">"Square of 2" : 4,</span></p><p class="c4 c1"><span class="c8 c0">"Square of 3" : 9,</span></p><p class="c4 c1"><span class="c8 c0">"Square of 4" : 16,</span></p><p class="c4 c1"><span class="c8 c0">"Square of 5" : 25,</span></p><p class="c4 c1"><span class="c8 c0">"Square of 6" : 36,</span></p><p class="c4 c1"><span class="c8 c0">"Square of 7" : 49,</span></p><p class="c4 c1"><span class="c8 c0">"Square of 8" : 64,</span></p><p class="c4 c1"><span class="c8 c0">"Square of 9" : 81,</span></p><p class="c4 c1"><span class="c8 c0">"Square of 10" : 100</span></p><p class="c4 c1"><span class="c8 c0">}</span></p><p class="c3 c1"><span></span></p><h2 class="c1"><a name="h.qe57mgdf5ql"></a><span>JSON as a subset of JSONiq</span></h2><p class="c9 c1"><span>As a rule of thumb, a well-formed JSON document is a JSONiq query as well. This means that you can copy-and-paste a JSON document into a query. The following are JSONiq queries that are "idempotent" (they just output themselves):</span></p><p class="c3 c1"><span></span></p><p class="c1"><span class="c0">{ "pi" : 3.14, "sq2" : 1.4 }</span></p><p class="c2 c1"><span class="c8 c0">{ "pi" : 3.14, "sq2" : 1.4 }</span></p><p class="c3 c1"><span class="c8 c0"></span></p><p class="c1"><span class="c0">[ 2, 3, 5, 7, 11, 13 ]</span></p><p class="c2 c1"><span class="c8 c0">[ 2, 3, 5, 7, 11, 13 ]</span></p><p class="c1 c3"><span class="c0"></span></p><p class="c1"><span class="c0">{</span></p><p class="c1"><span class="c0"> "operations" : [</span></p><p class="c1"><span class="c0"> { "binary" : [ "and", "or"] },</span></p><p class="c1"><span class="c0"> { "unary" : ["not"] }</span></p><p class="c1"><span class="c0"> ],</span></p><p class="c1"><span class="c0"> "bits" : [</span></p><p class="c1"><span class="c0"> 0, 1</span></p><p class="c1"><span class="c0"> ]</span></p><p class="c1"><span class="c0">}</span></p><p class="c1 c10"><span class="c8 c0">{</span></p><p class="c1 c10"><span class="c8 c0"> "operations" : [</span></p><p class="c1 c10"><span class="c8 c0"> { "binary" : [ "and", "or" ] },</span></p><p class="c1 c10"><span class="c8 c0"> { "unary" : [ "not" ] }</span></p><p class="c1 c10"><span class="c8 c0"> ],</span></p><p class="c1 c10"><span class="c8 c0"> "bits" : [</span></p><p class="c1 c10"><span class="c8 c0"> 0, 1</span></p><p class="c1 c10"><span class="c8 c0"> ]</span></p><p class="c1 c10"><span class="c8 c0">}</span></p><p class="c2 c3 c1"><span class="c8 c0"></span></p><p class="c9 c1"><span>This works with objects, arrays (even nested), strings, numbers, booleans, null. </span><span class="c14">The exceptions to this rule (but we are working on it!) are that:</span></p><p class="c9 c1"><span class="c14">(i) if a pair has a true, false or null value, there must be a space on at least one side of the colon (this will be fixed soon).</span></p><p class="c9 c1"><span class="c14">(ii) empty objects are not recognized</span></p><p class="c9 c1"><span class="c14">(iii) characters escaped with the \ in JSON strings are not recognized</span></p><p class="c3 c1"><span class="c14 c0"></span></p><p class="c9 c1"><span>It also works the other way round: if your query outputs an object or an array, you can directly use it as a JSON document.</span></p><p class="c2 c3 c1"><span class="c8 c0"></span></p><h1 class="c1"><a name="h.dewn8sw3husv"></a><span>JSON Navigation</span></h1><p class="c9 c1"><span>Up to now, you learnt how to compose expressions so as to do some computations and to build objects and arrays. It also works the other way round: if you have some JSON data, you can access it and navigate.</span></p><p class="c11 c3 c1"><span></span></p><p class="c9 c1"><span>All you need to know is: JSONiq views</span></p><ol class="c17" start="1"><li class="c1 c7"><span>an array as a sequence of values,</span></li><li class="c7 c1"><span>an object as a set of name/value pairs</span></li></ol><h2 class="c1 c9"><a name="h.zcnazhl6374z"></a><span>Objects</span></h2><p class="c9 c1"><span>If you use an object as a functor and provide it with a string, it will return the value associated with its parameter:</span></p><p class="c11 c3 c1"><span></span></p><p class="c1"><span class="c0">let $person := {</span></p><p class="c1"><span class="c0"> "first name" : "Sarah",</span></p><p class="c1"><span class="c0"> "age" : 13,</span></p><p class="c1"><span class="c0"> "gender" : "female",</span></p><p class="c1"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c1"><span class="c0">}</span></p><p class="c1"><span class="c0">return $person("first name")</span></p><p class="c2 c11 c1"><span class="c8 c0">"Sarah"</span></p><p class="c11 c3 c1"><span class="c8 c0"></span></p><p class="c1"><span>You can also ask for all keys in an object:</span></p><p class="c3 c1"><span></span></p><p class="c1"><span class="c0">let $person := {</span></p><p class="c1"><span class="c0"> "name" : "Sarah",</span></p><p class="c1"><span class="c0"> "age" : 13,</span></p><p class="c1"><span class="c0"> "gender" : "female",</span></p><p class="c1"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c1"><span class="c0">}</span></p><p class="c1"><span class="c0">return { "keys" : [ jn:keys($person)] }</span></p><p class="c11 c3 c1"><span class="c0"></span></p><p class="c2 c1 c23"><span class="c8 c0">{ "keys" : [ "name", "age", "gender", "friends" ] }</span></p><h2 class="c1"><a name="h.30wafxvenhgy"></a><span>Arrays</span></h2><p class="c9 c1"><span>If you use an array as a functor and provide it with an integer, it will return the corresponding entry:</span></p><p class="c11 c3 c1"><span></span></p><p class="c1"><span class="c0">let $friends := [ "Jim", "Mary", "Jennifer"]</span></p><p class="c1"><span class="c0">return $friends(2)</span></p><p class="c2 c11 c1"><span class="c8 c0">Mary</span></p><p class="c3 c1"><span class="c8 c0"></span></p><p class="c1"><span>It is also possible to get the size of an array:</span></p><p class="c11 c3 c1"><span></span></p><p class="c1"><span class="c0">let $person := {</span></p><p class="c1"><span class="c0"> "name" : "Sarah",</span></p><p class="c1"><span class="c0"> "age" : 13,</span></p><p class="c1"><span class="c0"> "gender" : "female",</span></p><p class="c1"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c1"><span class="c0">}</span></p><p class="c1"><span class="c0">return { "how many friends" : jn:size($person("friends")) }</span></p><p class="c11 c3 c1"><span class="c0"></span></p><p class="c2 c11 c1"><span class="c8 c0">{ "how many friends" : 3 }</span></p><p class="c11 c3 c1"><span class="c8 c0"></span></p><p class="c1"><span>For convenience, there is a function that returns all elements in an array, as a sequence:</span></p><p class="c11 c3 c1"><span></span></p><p class="c1"><span class="c0">let $person := {</span></p><p class="c1"><span class="c0"> "name" : "Sarah",</span></p><p class="c1"><span class="c0"> "age" : 13,</span></p><p class="c1"><span class="c0"> "gender" : "female",</span></p><p class="c1"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c1"><span class="c0">}</span></p><p class="c1"><span class="c0">return jn:members($person("friends"))</span></p><p class="c3 c1"><span class="c0"></span></p><p class="c2 c1 c11"><span class="c8 c0">Jim Mary Jennifer</span></p><h1 class="c1"><a name="h.eb0bxle2oykl"></a><span>Relational Algebra</span></h1><p class="c9 c1"><span>Remember last century's SELECT FROM WHERE statements? Well, JSONiq didn't throw out the baby with the bathwater. It has selection, projection and join capability.</span></p><p class="c3 c1"><span></span></p><p class="c1"><span class="c0">let $stores :=</span></p><p class="c1"><span class="c0">[</span></p><p class="c1"><span class="c0"> { "store number" : 1, "state" : "MA" },</span></p><p class="c1"><span class="c0"> { "store number" : 2, "state" : "MA" },</span></p><p class="c1"><span class="c0"> { "store number" : 3, "state" : "CA" },</span></p><p class="c1"><span class="c0"> { "store number" : 4, "state" : "CA" }</span></p><p class="c1"><span class="c0">]</span></p><p class="c1"><span class="c0">let $sales := [</span></p><p class="c1"><span class="c0"> { "product" : "broiler", "store number" : 1, "quantity" : 20 },</span></p><p class="c1"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 100 },</span></p><p class="c1"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 50 },</span></p><p class="c1"><span class="c0"> { "product" : "toaster", "store number" : 3, "quantity" : 50 },</span></p><p class="c1"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 100 },</span></p><p class="c1"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 150 },</span></p><p class="c1"><span class="c0"> { "product" : "socks", "store number" : 1, "quantity" : 500 },</span></p><p class="c1"><span class="c0"> { "product" : "socks", "store number" : 2, "quantity" : 10 },</span></p><p class="c1"><span class="c0"> { "product" : "shirt", "store number" : 3, "quantity" : 10 }</span></p><p class="c1"><span class="c0">]</span></p><p class="c1"><span class="c0">let $join :=</span></p><p class="c1"><span class="c0"> for $store in jn:members($stores), $sale in jn:members($sales)</span></p><p class="c1"><span class="c0"> where $store("store number") = $sale("store number")</span></p><p class="c1"><span class="c0"> return {</span></p><p class="c1"><span class="c0"> "nb" : $store("store number"),</span></p><p class="c1"><span class="c0"> "state" : $store("state"),</span></p><p class="c1"><span class="c0"> "sold" : $sale("product")</span></p><p class="c1"><span class="c0"> }</span></p><p class="c1"><span class="c0">return [$join]</span></p><p class="c15 c1"><span class="c8 c0">[ </span></p><p class="c15 c1"><span class="c8 c0">{ "nb" : 1, "state" : "MA", "sold" : "broiler" },</span></p><p class="c15 c1"><span class="c8 c0">{ "nb" : 1, "state" : "MA", "sold" : "socks" },</span></p><p class="c15 c1"><span class="c8 c0">{ "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c15 c1"><span class="c8 c0">{ "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c15 c1"><span class="c8 c0">{ "nb" : 2, "state" : "MA", "sold" : "socks" },</span></p><p class="c15 c1"><span class="c8 c0">{ "nb" : 3, "state" : "CA", "sold" : "toaster" },</span></p><p class="c1 c15"><span class="c8 c0">{ "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c15 c1"><span class="c8 c0">{ "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c15 c1"><span class="c8 c0">{ "nb" : 3, "state" : "CA", "sold" : "shirt" }</span></p><p class="c15 c1"><span class="c8 c0"> ]</span></p><h1 class="c1"><a name="h.oii6pvliilhi"></a><span>Access external data</span></h1><p class="c1"><span>Our implementation supports collections of JSON objects or arrays:</span></p><p class="c3 c1"><span></span></p><p class="c1"><span class="c0">dml:collection("my:data")</span></p><p class="c2 c1"><span class="c8 c0">{ "foo" : "Your" }</span></p><p class="c2 c1"><span class="c8 c0">{ "foo" : "Collection" }</span></p><p class="c2 c1"><span class="c8 c0">{ "foo" : "of" }</span></p><p class="c2 c1"><span class="c8 c0">{ "foo" : "JSON" }</span></p><p class="c2 c1"><span class="c8 c0">{ "foo" : "objects" }</span></p><p class="c2 c3 c1"><span class="c8 c0"></span></p><p class="c1"><span>It is also possible to get JSON content with an HTTP request, or by parsing it from a string. Functions that handle this are available.</span></p><p class="c3 c1"><span class="c8 c0"></span></p><h1 class="c1"><a name="h.fopcxnkoydgt"></a><span>JSON and XML</span></h1><p class="c9 c1"><span>You can readily use XML and JSON in the same program. If you put a JSON array in an XML constructor, it will be flattened (its member values are recursively taken, even in arrays of arrays). If you put a JSON pair in an XML constructor, it will be unboxed (its value is taken).</span></p><p class="c3 c1"><span></span></p><p class="c1"><span class="c0">let $data := {</span></p><p class="c1"><span class="c0"> "color" : "blue",</span></p><p class="c1"><span class="c0"> "closed" : true,</span></p><p class="c1"><span class="c0"> "points" : [[10,10], [20,10], [20,20], [10,20]]</span></p><p class="c1"><span class="c0">}</span></p><p class="c1"><span class="c0">let $stroke := attribute stroke { $data("color") }</span></p><p class="c1"><span class="c0">let $points := attribute points { jn:flatten($data("points")) }</span></p><p class="c1"><span class="c0">return</span></p><p class="c1"><span class="c0"> if ($data("closed")) then</span></p><p class="c1"><span class="c0"> <svg><polygon>{ $stroke, $points }</polygon></svg></span></p><p class="c1"><span class="c0"> else</span></p><p class="c1"><span class="c0"> <svg><polyline>{ $stroke, $points }</polyline></svg></span></p><p class="c3 c1"><span class="c0"></span></p><p class="c2 c1 c12"><span class="c8 c0"><?xml version="1.0" encoding="UTF-8"?></span></p><p class="c2 c1 c12"><span class="c8 c0"><svg><polygon stroke="blue" points="10 10 20 10 20 20 10 20"/></svg></span></p><p class="c3 c1"><span></span></p><h1 class="c1"><a name="h.bm3buqmzhtko"></a><span>I want more</span></h1><p class="c9 c1"><span>JSONiq supports JSON updates. You can declaratively update your JSON data. JSONiq provides functions that produce a list of updates. The list of updates that is eventually output by your program is then applied to your JSON data.</span></p><p class="c3 c1"><span></span></p><p class="c1"><span class="c0">copy $people := {</span></p><p class="c1"><span class="c0"> "John" : { "status" : "single" },</span></p><p class="c1"><span class="c0"> "Mary" : { "status" : "single" } }</span></p><p class="c1"><span class="c0">modify (replace json value of $people("John")("status") with "married",</span></p><p class="c1"><span class="c0"> replace json value of $people("Mary")("status") with "married")</span></p><p class="c1"><span class="c0">return $people</span></p><p class="c11 c3 c1"><span class="c0"></span></p><p class="c1 c2"><span class="c8 c0">{ "John" : { "status" : "married" }, "Mary" : { "status" : "married" } }</span></p><p class="c3 c1"><span></span></p><p class="c1"><span>JSONiq works with the XQuery 3.0 standard (switch, typeswitch and try-catch expressions, universal/existential quantifiers, path expressions, filtering expressions, functors, mappings, grouping, windowing will work). The Zorba implementation is also compatible with the proprietary Zorba scripting.</span></p><p class="c3 c1"><span></span></p><p class="c9 c1"><span>The complete JSONiq specification is available on </span><span class="c5"><a class="c13" href="http://www.jsoniq.org/">http://www.jsoniq.org/</a></span></p><p class="c3 c1"><span></span></p></body></html>
\ No newline at end of file
+<html><head><title>JSON for XQuery</title><style type="text/css">@import url('https://themes.googleusercontent.com/fonts/css?kit=lhDjYqiy3mZ0x6ROQEUoUw');ol{margin:0;padding:0}.c9{padding-left:0pt;text-align:justify;margin-left:36pt}.c7{list-style-type:disc;margin:0;padding:0}.c19{max-width:468pt;background-color:#ffffff;padding:72pt 72pt 72pt 72pt}.c20{color:inherit;text-decoration:inherit}.c11{text-indent:-13pt;margin-left:77pt}.c2{font-size:36pt;font-weight:bold}.c21{color:#1155cc;text-decoration:underline}.c16{font-weight:bold}.c3{color:#38761d}.c15{text-indent:120pt}.c22{color:#4a86e8}.c17{text-align:center}.c13{margin-left:49.5pt}.c6{text-align:right}.c10{text-indent:156pt}.c0{font-family:"Consolas"}.c12{text-indent:144pt}.c14{text-align:justify}.c8{text-indent:139.5pt}.c5{margin-left:144pt}.c18{font-style:italic}.c4{height:11pt}.c1{direction:ltr}.title{padding-top:24pt;line-height:1.15;text-align:center;color:#4a86e8;font-size:36pt;font-family:"Arial";font-weight:bold;padding-bottom:6pt}.subtitle{padding-top:18pt;line-height:1.15;text-align:left;color:#666666;font-style:italic;font-size:24pt;font-family:"Georgia";padding-bottom:4pt}li{color:#000000;font-size:11pt;font-family:"Arial"}p{color:#000000;font-size:11pt;margin:0;font-family:"Arial"}h1{padding-top:24pt;line-height:1.15;text-align:left;color:#4a86e8;font-size:24pt;font-family:"Arial";font-weight:bold;padding-bottom:6pt}h2{padding-top:18pt;line-height:1.15;text-align:left;color:#ff9900;font-size:18pt;font-family:"Arial";font-weight:bold;padding-bottom:4pt}h3{padding-top:14pt;line-height:1.15;text-align:left;color:#000000;font-size:14pt;font-family:"Arial";font-weight:bold;padding-bottom:4pt}h4{padding-top:12pt;line-height:1.15;text-align:left;color:#000000;font-size:12pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}h5{padding-top:11pt;line-height:1.15;text-align:left;color:#000000;font-size:11pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}h6{padding-top:10pt;line-height:1.15;text-align:left;color:#000000;font-size:10pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}</style></head><body class="c19"><p class="c17 c1"><span class="c2">JSONiq for XQuery users</span></p><p class="c4 c1 c15"><span></span></p><hr><p class="c1 c17"><span>This tutorial introduces the JSONiq language, which declaratively manipulates JSON data.</span></p><p class="c17 c1"><span>Why don't you go ahead can try the queries of this document on our online demo interface?</span></p><p class="c17 c1"><span> </span><span class="c21 c16"><a class="c20" href="http://www.zorba-xquery.com/html/jsoniq">http://www.zorba-xquery.com/html/jsoniq</a></span></p><hr><p class="c4 c1"><span></span></p><h1 class="c1"><a name="h.f453h84m2u1a"></a><span>JSON</span></h1><p class="c14 c1"><span>As explained on </span><span class="c21"><a class="c20" href="http://www.json.org/">http://www.json.org/</a></span><span>, JSON is a lightweight data-interchange format designed for humans as well as for computers. It supports as values:</span></p><ol class="c7" start="1"><li class="c9 c1"><span>objects (string-to-value map)</span></li><li class="c9 c1"><span>arrays (ordered sequence of values)</span></li><li class="c1 c9"><span>strings</span></li><li class="c9 c1"><span>numbers</span></li><li class="c9 c1"><span>booleans (true, false)</span></li><li class="c9 c1"><span>null</span></li></ol><p class="c4 c1"><span></span></p><p class="c1"><span>JSONiq extends XQuery to query and update JSON data, like XML data.</span></p><h1 class="c1"><a name="h.qtfakecy3fr7"></a><span>Elevator Pitch</span></h1><p class="c14 c1"><span>Here is an appetizer before we start the tutorial from scratch.</span></p><p class="c4 c1"><span></span></p><p class="c1"><span class="c0">let $stores :=</span></p><p class="c1"><span class="c0">[</span></p><p class="c1"><span class="c0"> { "store number" : 1, "state" : "MA" },</span></p><p class="c1"><span class="c0"> { "store number" : 2, "state" : "MA" },</span></p><p class="c1"><span class="c0"> { "store number" : 3, "state" : "CA" },</span></p><p class="c1"><span class="c0"> { "store number" : 4, "state" : "CA" }</span></p><p class="c1"><span class="c0">]</span></p><p class="c1"><span class="c0">let $sales := [</span></p><p class="c1"><span class="c0"> { "product" : "broiler", "store number" : 1, "quantity" : 20 },</span></p><p class="c1"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 100 },</span></p><p class="c1"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 50 },</span></p><p class="c1"><span class="c0"> { "product" : "toaster", "store number" : 3, "quantity" : 50 },</span></p><p class="c1"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 100 },</span></p><p class="c1"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 150 },</span></p><p class="c1"><span class="c0"> { "product" : "socks", "store number" : 1, "quantity" : 500 },</span></p><p class="c1"><span class="c0"> { "product" : "socks", "store number" : 2, "quantity" : 10 },</span></p><p class="c1"><span class="c0"> { "product" : "shirt", "store number" : 3, "quantity" : 10 }</span></p><p class="c1"><span class="c0">]</span></p><p class="c1"><span class="c0">let $join :=</span></p><p class="c1"><span class="c0"> for $store in jn:members($stores), $sale in jn:members($sales)</span></p><p class="c1"><span class="c0"> where $store("store number") = $sale("store number")</span></p><p class="c1"><span class="c0"> return {</span></p><p class="c1"><span class="c0"> "nb" : $store("store number"),</span></p><p class="c1"><span class="c0"> "state" : $store("state"),</span></p><p class="c1"><span class="c0"> "sold" : $sale("product")</span></p><p class="c1"><span class="c0"> }</span></p><p class="c1"><span class="c0">return [$join]</span></p><p class="c5 c1"><span class="c3 c0">[ </span></p><p class="c5 c1"><span class="c3 c0"> { "nb" : 1, "state" : "MA", "sold" : "broiler" },</span></p><p class="c5 c1"><span class="c3 c0"> { "nb" : 1, "state" : "MA", "sold" : "socks" },</span></p><p class="c5 c1"><span class="c3 c0"> { "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c5 c1"><span class="c3 c0"> { "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c5 c1"><span class="c3 c0"> { "nb" : 2, "state" : "MA", "sold" : "socks" },</span></p><p class="c5 c1"><span class="c3 c0"> { "nb" : 3, "state" : "CA", "sold" : "toaster" },</span></p><p class="c5 c1"><span class="c3 c0"> { "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c5 c1"><span class="c3 c0"> { "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c5 c1"><span class="c3 c0"> { "nb" : 3, "state" : "CA", "sold" : "shirt" }</span></p><p class="c5 c1"><span class="c3 c0"> ]</span></p><p class="c4 c1"><span></span></p><h1 class="c1"><a name="h.yugk1mszt0re"></a><span>And here you go</span></h1><h2 class="c1"><a name="h.39rm37noeh9g"></a><span>JSONiq types</span></h2><p class="c1"><span>JSONiq maps JSON types to the XQuery data model. Numbers are xs:integer, xs:decimal or xs:double, strings are xs:string, true and false are xs:boolean and null is the unique value of a new atomic type jn:null.</span></p><p class="c4 c1"><span></span></p><p class="c1"><span>By default, in JSONiq, for convenience, true, false and null are recognized as literals instead of the classical XQuery path expression semantics (i.e., they would otherwise navigate to XML elements named "true", "false" or "null"). However, this can be deactivated to use the path expression semantics.</span></p><p class="c4 c1"><span></span></p><p class="c1"><span>JSONiq also introduces new items: objects and arrays. Objects are sets of key/value pairs. Arrays have members which are values. Values are objects, arrays, XML nodes, functions or atomic items. Note that, in particular, Arrays can nest, unlike sequences.</span></p><p class="c4 c1"><span></span></p><p class="c1"><span>The new item types for objects and arrays are object() and array(). json-item() is a supertype of both. structured-item() is a supertype for json-item() and node().</span></p><h2 class="c1"><a name="h.j0wg8654ivtw"></a><span>JSON Constructors</span></h2><p class="c1"><span>JSONiq introduces JSON constructors, in a similar way to XML constructors.</span></p><p class="c4 c1"><span></span></p><p class="c1"><span>You can put any expression in a array. The items in the sequence produced by the expression will become members of the array:</span></p><p class="c4 c1"><span></span></p><p class="c1"><span class="c0">[ 1 to 10 ]</span></p><p class="c6 c1"><span class="c3 c0">[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]</span></p><p class="c6 c4 c1"><span class="c3 c0"></span></p><p class="c1"><span>Or you can dynamically compute an object:</span></p><p class="c4 c1"><span></span></p><p class="c1"><span class="c0">{</span></p><p class="c1"><span class="c0"> "Greeting" : let $d := "Mister Spock"</span></p><p class="c1"><span class="c0"> return concat("Hello, ", $d),</span></p><p class="c1"><span class="c0"> "Farewell" : string-join(("Live", "long", "and", "prosper"),</span></p><p class="c1"><span class="c0"> " ")</span></p><p class="c1"><span class="c0">}</span></p><p class="c4 c1"><span class="c3 c0"></span></p><p class="c6 c1"><span class="c3 c0">{ "Greeting" : "Hello, Mister Spock", "Farewell" : "Live long and prosper" }</span></p><p class="c4 c1"><span class="c3"></span></p><p class="c1"><span>You can also dynamically generate singleton objects:</span></p><p class="c4 c1"><span class="c0"></span></p><p class="c1"><span class="c0">{ concat("Square of ", 2) : 2 * 2 }</span></p><p class="c6 c1"><span class="c3 c0">{ "Square of 2" : 4 }</span></p><p class="c6 c4 c1"><span class="c3 c0"></span></p><p class="c1"><span>and then use the {| |} construct to wrap several of them in a bigger object:</span></p><p class="c4 c1"><span class="c0"></span></p><p class="c1"><span class="c0">{|</span></p><p class="c1"><span class="c0"> for $i in 1 to 10</span></p><p class="c1"><span class="c0"> return { concat("Square of ", $i) : $i * $i }</span></p><p class="c1"><span class="c0">|}</span></p><p class="c5 c1"><span class="c3 c0">{</span></p><p class="c5 c1"><span class="c3 c0">"Square of 1" : 1,</span></p><p class="c5 c1"><span class="c3 c0">"Square of 2" : 4,</span></p><p class="c5 c1"><span class="c3 c0">"Square of 3" : 9,</span></p><p class="c1 c5"><span class="c3 c0">"Square of 4" : 16,</span></p><p class="c5 c1"><span class="c3 c0">"Square of 5" : 25,</span></p><p class="c5 c1"><span class="c3 c0">"Square of 6" : 36,</span></p><p class="c5 c1"><span class="c3 c0">"Square of 7" : 49,</span></p><p class="c5 c1"><span class="c3 c0">"Square of 8" : 64,</span></p><p class="c5 c1"><span class="c3 c0">"Square of 9" : 81,</span></p><p class="c5 c1"><span class="c3 c0">"Square of 10" : 100</span></p><p class="c5 c1"><span class="c3 c0">}</span></p><p class="c4 c1"><span></span></p><h2 class="c1"><a name="h.qe57mgdf5ql"></a><span>JSON as a subset of JSONiq</span></h2><p class="c14 c1"><span>As a rule of thumb, a well-formed JSON document is a JSONiq expression as well. This means that you can copy-and-paste a JSON document into a query. The following are JSONiq queries that are "idempotent" (they just output themselves):</span></p><p class="c4 c1"><span></span></p><p class="c1"><span class="c0">{ "pi" : 3.14, "sq2" : 1.4 }</span></p><p class="c6 c1"><span class="c3 c0">{ "pi" : 3.14, "sq2" : 1.4 }</span></p><p class="c1 c4"><span class="c3 c0"></span></p><p class="c1"><span class="c0">[ 2, 3, 5, 7, 11, 13 ]</span></p><p class="c6 c1"><span class="c3 c0">[ 2, 3, 5, 7, 11, 13 ]</span></p><p class="c4 c1"><span class="c0"></span></p><p class="c1"><span class="c0">{</span></p><p class="c1"><span class="c0"> "operations" : [</span></p><p class="c1"><span class="c0"> { "binary" : [ "and", "or"] },</span></p><p class="c1"><span class="c0"> { "unary" : ["not"] }</span></p><p class="c1"><span class="c0"> ],</span></p><p class="c1"><span class="c0"> "bits" : [</span></p><p class="c1"><span class="c0"> 0, 1</span></p><p class="c1"><span class="c0"> ]</span></p><p class="c1"><span class="c0">}</span></p><p class="c12 c1"><span class="c0 c3">{</span></p><p class="c12 c1"><span class="c3 c0"> "operations" : [</span></p><p class="c12 c1"><span class="c3 c0"> { "binary" : [ "and", "or" ] },</span></p><p class="c1 c12"><span class="c3 c0"> { "unary" : [ "not" ] }</span></p><p class="c12 c1"><span class="c3 c0"> ],</span></p><p class="c12 c1"><span class="c3 c0"> "bits" : [</span></p><p class="c12 c1"><span class="c3 c0"> 0, 1</span></p><p class="c12 c1"><span class="c3 c0"> ]</span></p><p class="c12 c1"><span class="c3 c0">}</span></p><p class="c6 c4 c1"><span class="c3 c0"></span></p><p class="c14 c1"><span>This works with objects, arrays (even nested), strings, numbers, booleans, null. </span><span class="c18">The exceptions to this rule (but we are working on it!) are that:</span></p><p class="c14 c1"><span class="c18">(i) empty objects are not recognized</span></p><p class="c14 c1"><span class="c18">(ii) characters escaped with the \ in JSON strings are not recognized, XML character references are recognized instead.</span></p><p class="c4 c1"><span class="c0 c18"></span></p><p class="c14 c1"><span>It also works the other way round: if your query outputs an object or an array, you can directly use it as a JSON document.</span></p><p class="c6 c4 c1"><span class="c3 c0"></span></p><h1 class="c1"><a name="h.dewn8sw3husv"></a><span>JSON Navigation</span></h1><p class="c14 c1"><span>Up to now, you learnt how to compose expressions so as to do some computations and to build objects and arrays. It also works the other way round: if you have some JSON data, you can access it and navigate.</span></p><p class="c10 c4 c1"><span></span></p><p class="c14 c1"><span>All you need to know is: JSONiq views</span></p><ol class="c7" start="1"><li class="c9 c1"><span>an array as an ordered list of values,</span></li><li class="c9 c1"><span>an object as a set of name/value pairs</span></li></ol><h2 class="c14 c1"><a name="h.zcnazhl6374z"></a><span>Objects</span></h2><p class="c14 c1"><span>You can use an object as if it were a function and pass the call an argument of type xs:string. It will return the value associated thereto:</span></p><p class="c10 c4 c1"><span></span></p><p class="c1"><span class="c0">let $person := {</span></p><p class="c1"><span class="c0"> "first name" : "Sarah",</span></p><p class="c1"><span class="c0"> "age" : 13,</span></p><p class="c1"><span class="c0"> "gender" : "female",</span></p><p class="c1"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c1"><span class="c0">}</span></p><p class="c1"><span class="c0">return $person("first name")</span></p><p class="c6 c10 c1"><span class="c3 c0">"Sarah"</span></p><p class="c10 c4 c1"><span class="c3 c0"></span></p><p class="c1"><span>You can also ask for all keys in an object:</span></p><p class="c4 c1"><span></span></p><p class="c1"><span class="c0">let $person := {</span></p><p class="c1"><span class="c0"> "name" : "Sarah",</span></p><p class="c1"><span class="c0"> "age" : 13,</span></p><p class="c1"><span class="c0"> "gender" : "female",</span></p><p class="c1"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c1"><span class="c0">}</span></p><p class="c1"><span class="c0">return { "keys" : [ jn:keys($person)] }</span></p><p class="c10 c4 c1"><span class="c0"></span></p><p class="c6 c1 c11"><span class="c3 c0">{ "keys" : [ "name", "age", "gender", "friends" ] }</span></p><h2 class="c1"><a name="h.30wafxvenhgy"></a><span>Arrays</span></h2><p class="c14 c1"><span>You can use an array as if it were a function and pass the call an argument of type xs:integer. It will return the entry at that position:</span></p><p class="c10 c4 c1"><span></span></p><p class="c1"><span class="c0">let $friends := [ "Jim", "Mary", "Jennifer"]</span></p><p class="c1"><span class="c0">return $friends(2)</span></p><p class="c6 c10 c1"><span class="c3 c0">Mary</span></p><p class="c4 c1"><span class="c3 c0"></span></p><p class="c1"><span>It is also possible to get the size of an array:</span></p><p class="c4 c1 c10"><span></span></p><p class="c1"><span class="c0">let $person := {</span></p><p class="c1"><span class="c0"> "name" : "Sarah",</span></p><p class="c1"><span class="c0"> "age" : 13,</span></p><p class="c1"><span class="c0"> "gender" : "female",</span></p><p class="c1"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c1"><span class="c0">}</span></p><p class="c1"><span class="c0">return { "how many friends" : jn:size($person("friends")) }</span></p><p class="c10 c4 c1"><span class="c0"></span></p><p class="c6 c10 c1"><span class="c3 c0">{ "how many friends" : 3 }</span></p><p class="c10 c4 c1"><span class="c3 c0"></span></p><p class="c1"><span>For convenience, there is a function that returns all elements in an array, as a sequence:</span></p><p class="c10 c4 c1"><span></span></p><p class="c1"><span class="c0">let $person := {</span></p><p class="c1"><span class="c0"> "name" : "Sarah",</span></p><p class="c1"><span class="c0"> "age" : 13,</span></p><p class="c1"><span class="c0"> "gender" : "female",</span></p><p class="c1"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c1"><span class="c0">}</span></p><p class="c1"><span class="c0">return jn:members($person("friends"))</span></p><p class="c4 c1"><span class="c0"></span></p><p class="c6 c10 c1"><span class="c3 c0">Jim Mary Jennifer</span></p><h1 class="c1"><a name="h.eb0bxle2oykl"></a><span>Relational Algebra</span></h1><p class="c14 c1"><span>Remember SQL's SELECT FROM WHERE statements? JSONiq inherits selection, projection and join capability from XQuery FLWOR expressions. In order to traverse an array, jn:members() converts it into a sequence which can then be iterated over by a FLWOR expression.</span></p><p class="c4 c1"><span></span></p><p class="c1"><span class="c0">let $stores :=</span></p><p class="c1"><span class="c0">[</span></p><p class="c1"><span class="c0"> { "store number" : 1, "state" : "MA" },</span></p><p class="c1"><span class="c0"> { "store number" : 2, "state" : "MA" },</span></p><p class="c1"><span class="c0"> { "store number" : 3, "state" : "CA" },</span></p><p class="c1"><span class="c0"> { "store number" : 4, "state" : "CA" }</span></p><p class="c1"><span class="c0">]</span></p><p class="c1"><span class="c0">let $sales := [</span></p><p class="c1"><span class="c0"> { "product" : "broiler", "store number" : 1, "quantity" : 20 },</span></p><p class="c1"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 100 },</span></p><p class="c1"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 50 },</span></p><p class="c1"><span class="c0"> { "product" : "toaster", "store number" : 3, "quantity" : 50 },</span></p><p class="c1"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 100 },</span></p><p class="c1"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 150 },</span></p><p class="c1"><span class="c0"> { "product" : "socks", "store number" : 1, "quantity" : 500 },</span></p><p class="c1"><span class="c0"> { "product" : "socks", "store number" : 2, "quantity" : 10 },</span></p><p class="c1"><span class="c0"> { "product" : "shirt", "store number" : 3, "quantity" : 10 }</span></p><p class="c1"><span class="c0">]</span></p><p class="c1"><span class="c0">let $join :=</span></p><p class="c1"><span class="c0"> for $store in jn:members($stores), $sale in jn:members($sales)</span></p><p class="c1"><span class="c0"> where $store("store number") = $sale("store number")</span></p><p class="c1"><span class="c0"> return {</span></p><p class="c1"><span class="c0"> "nb" : $store("store number"),</span></p><p class="c1"><span class="c0"> "state" : $store("state"),</span></p><p class="c1"><span class="c0"> "sold" : $sale("product")</span></p><p class="c1"><span class="c0"> }</span></p><p class="c1"><span class="c0">return [$join]</span></p><p class="c8 c1"><span class="c3 c0">[ </span></p><p class="c8 c1"><span class="c3 c0">{ "nb" : 1, "state" : "MA", "sold" : "broiler" },</span></p><p class="c8 c1"><span class="c3 c0">{ "nb" : 1, "state" : "MA", "sold" : "socks" },</span></p><p class="c1 c8"><span class="c3 c0">{ "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c8 c1"><span class="c3 c0">{ "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c8 c1"><span class="c3 c0">{ "nb" : 2, "state" : "MA", "sold" : "socks" },</span></p><p class="c8 c1"><span class="c3 c0">{ "nb" : 3, "state" : "CA", "sold" : "toaster" },</span></p><p class="c8 c1"><span class="c3 c0">{ "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c8 c1"><span class="c3 c0">{ "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c8 c1"><span class="c3 c0">{ "nb" : 3, "state" : "CA", "sold" : "shirt" }</span></p><p class="c8 c1"><span class="c3 c0"> ]</span></p><h1 class="c1"><a name="h.oii6pvliilhi"></a><span>Access external data</span></h1><p class="c1"><span>Our implementation supports collections of (and indices on) JSON objects or arrays:</span></p><p class="c4 c1"><span></span></p><p class="c1"><span class="c0">dml:collection("my:data")</span></p><p class="c6 c1"><span class="c3 c0">{ "foo" : "Your" }</span></p><p class="c6 c1"><span class="c3 c0">{ "foo" : "Collection" }</span></p><p class="c6 c1"><span class="c3 c0">{ "foo" : "of" }</span></p><p class="c6 c1"><span class="c3 c0">{ "foo" : "JSON" }</span></p><p class="c6 c1"><span class="c3 c0">{ "foo" : "objects" }</span></p><p class="c4 c1 c6"><span class="c3 c0"></span></p><p class="c1"><span>It is also possible to get JSON content with an HTTP request, or by parsing it from a string. The EXPath http-client module (described in the Zorba documentation) allows you to make HTTP requests, and the jn:parse-json() function allows you to use the body as an object or an array.</span></p><p class="c4 c1"><span class="c3 c0"></span></p><h1 class="c1"><a name="h.fopcxnkoydgt"></a><span>JSON and XML</span></h1><p class="c14 c1"><span>You can use XML and JSON in the same program. An XML node can be a value in an object or array, however, arrays and object may not be children of an XML node - but you can extract atomic values or XML nodes inside objects and arrays to insert them in a new XML node.</span></p><p class="c4 c1"><span></span></p><p class="c1"><span class="c0">let $data := {</span></p><p class="c1"><span class="c0"> "color" : "blue",</span></p><p class="c1"><span class="c0"> "closed" : true,</span></p><p class="c1"><span class="c0"> "points" : [[10,10], [20,10], [20,20], [10,20]]</span></p><p class="c1"><span class="c0">}</span></p><p class="c1"><span class="c0">let $stroke := attribute stroke { $data("color") }</span></p><p class="c1"><span class="c0">let $points := attribute points { jn:flatten($data("points")) }</span></p><p class="c1"><span class="c0">return</span></p><p class="c1"><span class="c0"> if ($data("closed")) then</span></p><p class="c1"><span class="c0"> <svg><polygon>{ $stroke, $points }</polygon></svg></span></p><p class="c1"><span class="c0"> else</span></p><p class="c1"><span class="c0"> <svg><polyline>{ $stroke, $points }</polyline></svg></span></p><p class="c4 c1"><span class="c0"></span></p><p class="c13 c6 c1"><span class="c3 c0"><?xml version="1.0" encoding="UTF-8"?></span></p><p class="c6 c1 c13"><span class="c3 c0"><svg><polygon stroke="blue" points="10 10 20 10 20 20 10 20"/></svg></span></p><p class="c4 c1"><span></span></p><h1 class="c1"><a name="h.bm3buqmzhtko"></a><span>I want more</span></h1><p class="c1 c14"><span>JSONiq supports JSON updates by extending the XQuery Update Facility specification, so you can declaratively update your JSON data. JSONiq provides new expressions that produce update primitives on JSON items. The list of updates that is eventually output by your program is then applied to your JSON data.</span></p><p class="c4 c1"><span></span></p><p class="c1"><span class="c0">copy $people := {</span></p><p class="c1"><span class="c0"> "John" : { "status" : "single" },</span></p><p class="c1"><span class="c0"> "Mary" : { "status" : "single" } }</span></p><p class="c1"><span class="c0">modify (replace json value of $people("John")("status") with "married",</span></p><p class="c1"><span class="c0"> replace json value of $people("Mary")("status") with "married")</span></p><p class="c1"><span class="c0">return $people</span></p><p class="c10 c4 c1"><span class="c0"></span></p><p class="c6 c1"><span class="c3 c0">{ "John" : { "status" : "married" }, "Mary" : { "status" : "married" } }</span></p><p class="c4 c1"><span></span></p><p class="c1"><span>JSONiq works with the XQuery 3.0 standard (switch, typeswitch and try-catch expressions, universal/existential quantifiers, path expressions, filtering expressions, functors, mappings, grouping, windowing will work). The Zorba implementation is also compatible with the proprietary Zorba scripting.</span></p><p class="c4 c1"><span></span></p><p class="c14 c1"><span>The complete JSONiq specification is available on </span><span class="c21"><a class="c20" href="http://www.jsoniq.org/">http://www.jsoniq.org/</a></span></p><p class="c4 c1"><span></span></p></body></html>
\ No newline at end of file
=== modified file 'doc/zorba/XQueryforJSON.html'
--- doc/zorba/XQueryforJSON.html 2012-07-25 13:42:21 +0000
+++ doc/zorba/XQueryforJSON.html 2012-08-20 13:39:02 +0000
@@ -1,1 +1,1 @@
-<html><head><title>XQuery for JSON</title><style type="text/css">@import url('https://themes.googleusercontent.com/fonts/css?kit=lhDjYqiy3mZ0x6ROQEUoUw');ol{margin:0;padding:0}.c19{list-style-type:disc;margin:0;padding:0}.c21{max-width:468pt;background-color:#ffffff;padding:72pt 72pt 72pt 72pt}.c16{text-indent:-13.5pt;margin-left:76.5pt}.c4{height:11pt;text-align:right}.c7{padding-left:0pt;text-align:justify}.c1{color:#1155cc;text-decoration:underline}.c14{color:inherit;text-decoration:inherit}.c3{direction:ltr}.c20{height:18pt}.c8{margin-left:144pt}.c22{color:#ff9900}.c9{text-align:right}.c15{color:#4a86e8}.c13{font-style:italic}.c17{font-weight:bold}.c6{margin-left:36pt}.c12{margin-left:18pt}.c18{color:#ff0000}.c0{font-family:"Consolas"}.c10{text-align:justify}.c2{color:#38761d}.c5{height:11pt}.c11{text-align:center}.title{padding-top:24pt;line-height:1.15;text-align:center;color:#4a86e8;font-size:36pt;font-family:"Arial";font-weight:bold;padding-bottom:6pt}.subtitle{padding-top:18pt;line-height:1.15;text-align:left;color:#666666;font-style:italic;font-size:24pt;font-family:"Georgia";padding-bottom:4pt}li{color:#000000;font-size:11pt;font-family:"Arial"}p{color:#000000;font-size:11pt;margin:0;font-family:"Arial"}h1{padding-top:24pt;line-height:1.15;text-align:left;color:#4a86e8;font-size:24pt;font-family:"Arial";font-weight:bold;padding-bottom:6pt}h2{padding-top:18pt;line-height:1.15;text-align:left;color:#ff9900;font-size:18pt;font-family:"Arial";font-weight:bold;padding-bottom:4pt}h3{padding-top:14pt;line-height:1.15;text-align:left;color:#000000;font-size:14pt;font-family:"Arial";font-weight:bold;padding-bottom:4pt}h4{padding-top:12pt;line-height:1.15;text-align:left;color:#000000;font-size:12pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}h5{padding-top:11pt;line-height:1.15;text-align:left;color:#000000;font-size:11pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}h6{padding-top:10pt;line-height:1.15;text-align:left;color:#000000;font-size:10pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}</style></head><body class="c21"><p class="c3 title"><a name="h.li2wdq8unbq"></a><span>JSONiq for JSON users</span></p><p class="c3 title"><a name="h.5ipqqclfxk4n"></a><span class="c2">XQuery for JSON</span></p><hr><p class="c3 c11"><span>This tutorial introduces the JSONiq language, which declaratively manipulates JSON data.</span></p><p class="c3 c11"><span>Why don't you go ahead can try the queries of this document on our online demo interface?</span></p><p class="c3 c11"><span> </span><span class="c1 c17"><a class="c14" href="http://jsoniq.zorba-xquery.com/">http://jsoniq.zorba-xquery.com/</a></span></p><hr><p class="c3 c5"><span></span></p><h2 class="c3 c20"><a name="h.8gra0ylxutrv"></a></h2><p class="c3 c12"><span class="c1"><a class="c14" href="#h.f453h84m2u1a">JSON</a></span></p><p class="c3 c12"><span class="c1"><a class="c14" href="#h.qtfakecy3fr7">Elevator Pitch</a></span></p><p class="c3 c12"><span class="c1"><a class="c14" href="#h.yugk1mszt0re">And here you go</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.4uvhbej4btrt">Like Monsieur Jourdain, you already knew some JSONiq</a></span></p><p class="c3 c12"><span class="c1"><a class="c14" href="#h.1gal1zhyffu4">JSONiq basics</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.ncbxtez2z3rn">The real JSONiq Hello, World!</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.ifcjheuaxoqc">Numbers and arithmetic operations</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.jmbc6c1fqqwx">Logical operations</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.iq1ixg5ywx0r">Strings</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.rv6w8p4wenfa">Sequences</a></span></p><p class="c3 c12"><span class="c1"><a class="c14" href="#h.7x2r8sj1zjwe">A bit more in depth</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.b6c9zq9um8cu">Variables</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.92ak2udyfghp">Iteration</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.zdhx60a5duyu">Conditions</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.ccs6lkxiixw4">Composability of Expressions</a></span></p><p class="c3 c12"><span class="c1"><a class="c14" href="#h.mjv7kyjurri2">JSON Navigation</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.xosiyb17dh24">Objects</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.mrf42gizl3y6">Arrays</a></span></p><p class="c3 c12"><span class="c1"><a class="c14" href="#h.eb0bxle2oykl">Relational Algebra</a></span></p><p class="c3 c12"><span class="c1"><a class="c14" href="#h.oii6pvliilhi">Access external data</a></span></p><p class="c3 c12"><span class="c1"><a class="c14" href="#h.bm3buqmzhtko">I want more</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.5itcphr8262b">Even more</a></span></p><p class="c3 c6"><span class="c1"><a class="c14" href="#h.j7oh3cyhem38">More is not enough</a></span></p><p class="c3 c5"><span></span></p><h1 class="c3"><a name="h.f453h84m2u1a"></a><span>JSON</span></h1><p class="c3 c10"><span>As explained on </span><span class="c1"><a class="c14" href="http://www.json.org/">http://www.json.org/</a></span><span>, JSON is a lightweight data-interchange format designed for humans as well as for computers. It supports as values:</span></p><ol class="c19" start="1"><li class="c7 c3 c6"><span>objects (string-to-value map)</span></li><li class="c7 c3 c6"><span>arrays (ordered sequence of values)</span></li><li class="c7 c3 c6"><span>strings</span></li><li class="c3 c6 c7"><span>numbers</span></li><li class="c7 c3 c6"><span>booleans (true, false)</span></li><li class="c7 c3 c6"><span>null</span></li></ol><p class="c3 c5"><span></span></p><p class="c3"><span>JSONiq provides declarative querying and updating capabilities on JSON data.</span></p><h1 class="c3"><a name="h.qtfakecy3fr7"></a><span>Elevator Pitch</span></h1><p class="c3 c10"><span>JSONiq is based on XQuery, which is a W3C standard (like XML and HTML). XQuery is a very powerful declarative language that manipulates XML data, but that is also a very good fit for JSON. Here is an appetizer before we start the tutorial from scratch.</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">let $stores :=</span></p><p class="c3"><span class="c0">[</span></p><p class="c3"><span class="c0"> { "store number" : 1, "state" : "MA" },</span></p><p class="c3"><span class="c0"> { "store number" : 2, "state" : "MA" },</span></p><p class="c3"><span class="c0"> { "store number" : 3, "state" : "CA" },</span></p><p class="c3"><span class="c0"> { "store number" : 4, "state" : "CA" }</span></p><p class="c3"><span class="c0">]</span></p><p class="c3"><span class="c0">let $sales := [</span></p><p class="c3"><span class="c0"> { "product" : "broiler", "store number" : 1, "quantity" : 20 },</span></p><p class="c3"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 100 },</span></p><p class="c3"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 50 },</span></p><p class="c3"><span class="c0"> { "product" : "toaster", "store number" : 3, "quantity" : 50 },</span></p><p class="c3"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 100 },</span></p><p class="c3"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 150 },</span></p><p class="c3"><span class="c0"> { "product" : "socks", "store number" : 1, "quantity" : 500 },</span></p><p class="c3"><span class="c0"> { "product" : "socks", "store number" : 2, "quantity" : 10 },</span></p><p class="c3"><span class="c0"> { "product" : "shirt", "store number" : 3, "quantity" : 10 }</span></p><p class="c3"><span class="c0">]</span></p><p class="c3"><span class="c0">let $join :=</span></p><p class="c3"><span class="c0"> for $store in jn:members($stores), $sale in jn:members($sales)</span></p><p class="c3"><span class="c0"> where $store("store number") = $sale("store number")</span></p><p class="c3"><span class="c0"> return {</span></p><p class="c3"><span class="c0"> "nb" : $store("store number"),</span></p><p class="c3"><span class="c0"> "state" : $store("state"),</span></p><p class="c3"><span class="c0"> "sold" : $sale("product")</span></p><p class="c3"><span class="c0"> }</span></p><p class="c3"><span class="c0">return [$join]</span></p><p class="c3 c8"><span class="c0 c2">[ </span></p><p class="c3 c8"><span class="c0 c2"> { "nb" : 1, "state" : "MA", "sold" : "broiler" },</span></p><p class="c3 c8"><span class="c0 c2"> { "nb" : 1, "state" : "MA", "sold" : "socks" },</span></p><p class="c3 c8"><span class="c0 c2"> { "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c3 c8"><span class="c0 c2"> { "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c3 c8"><span class="c0 c2"> { "nb" : 2, "state" : "MA", "sold" : "socks" },</span></p><p class="c3 c8"><span class="c0 c2"> { "nb" : 3, "state" : "CA", "sold" : "toaster" },</span></p><p class="c3 c8"><span class="c0 c2"> { "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c3 c8"><span class="c0 c2"> { "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c3 c8"><span class="c0 c2"> { "nb" : 3, "state" : "CA", "sold" : "shirt" }</span></p><p class="c3 c8"><span class="c0 c2"> ]</span></p><p class="c3 c5"><span></span></p><h1 class="c3"><a name="h.yugk1mszt0re"></a><span>And here you go</span></h1><h2 class="c3"><a name="h.4uvhbej4btrt"></a><span>Like Monsieur Jourdain, you already knew some JSONiq</span></h2><p class="c3 c10"><span>The first thing you need to know is that, as a rule of thumb, a well-formed JSON document is a JSONiq query as well.</span></p><p class="c3 c5"><span></span></p><p class="c3 c10"><span>This means that, most of the time, you can copy-and-paste a JSON document into a query. The following are JSONiq queries that are "idempotent" (they just output themselves):</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">{ "pi" : 3.14, "sq2" : 1.4 }</span></p><p class="c3 c9"><span class="c0 c2">{ "pi" : 3.14, "sq2" : 1.4 }</span></p><p class="c3 c5"><span class="c0 c2"></span></p><p class="c3"><span class="c0">[ 2, 3, 5, 7, 11, 13 ]</span></p><p class="c3 c9"><span class="c0 c2">[ 2, 3, 5, 7, 11, 13 ]</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span class="c0">{</span></p><p class="c3"><span class="c0"> "operations" : [</span></p><p class="c3"><span class="c0"> { "binary" : [ "and", "or"] },</span></p><p class="c3"><span class="c0"> { "unary" : ["not"] }</span></p><p class="c3"><span class="c0"> ],</span></p><p class="c3"><span class="c0"> "bits" : [</span></p><p class="c3"><span class="c0"> 0, 1</span></p><p class="c3"><span class="c0"> ]</span></p><p class="c3"><span class="c0">}</span></p><p class="c3 c8"><span class="c0 c2">{</span></p><p class="c3 c8"><span class="c0 c2"> "operations" : [</span></p><p class="c3 c8"><span class="c0 c2"> { "binary" : [ "and", "or" ] },</span></p><p class="c3 c8"><span class="c0 c2"> { "unary" : [ "not" ] }</span></p><p class="c3 c8"><span class="c0 c2"> ],</span></p><p class="c3 c8"><span class="c0 c2"> "bits" : [</span></p><p class="c3 c8"><span class="c0 c2"> 0, 1</span></p><p class="c3 c8"><span class="c0 c2"> ]</span></p><p class="c3 c8"><span class="c0 c2">}</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3"><span class="c0">[ { "Question" : "Ultimate" }, ["Life", "The universe", "and everything"] ]</span></p><p class="c4 c3"><span class="c0"></span></p><p class="c3 c9"><span class="c0 c2">[ { "Question" : "Ultimate" }, [ "Life", "The universe", "and everything" ] ]</span></p><p class="c4 c3"><span class="c0"></span></p><p class="c3"><span>This works with objects, arrays (even nested), strings, numbers, booleans, null. </span><span class="c13">The exceptions to this rule (but we are working on it!) are that:</span></p><p class="c3 c10"><span class="c13">(i) if a pair has a true, false or null value, there must be a space on at least one side of the colon (this will be fixed soon).</span></p><p class="c3 c10"><span class="c13">(ii) empty objects are not recognized and must be written {| |}</span></p><p class="c3 c10"><span class="c13">(iii) characters escaped with the \ in JSON strings are not recognized</span></p><p class="c3 c5"><span class="c13 c18 c0"></span></p><p class="c3 c10"><span>It also works the other way round: if your query outputs an object or an array, you can directly use it as a JSON document.</span></p><p class="c3 c5"><span></span></p><p class="c3 c10"><span>JSONiq is a declarative language. This means that you only need to say </span><span class="c13">what</span><span> you want - the compiler will take care of the </span><span class="c13">how</span><span>. In the above queries, you are basically saying: I want to output this JSON content, and here it is.</span></p><h1 class="c3"><a name="h.1gal1zhyffu4"></a><span>JSONiq basics</span></h1><h2 class="c3"><a name="h.ncbxtez2z3rn"></a><span>The real JSONiq Hello, World!</span></h2><p class="c3"><span>Wondering what a hello world program looks like in JSONiq? Here it is:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">"Hello, World!"</span></p><p class="c3 c9"><span class="c0 c2">Hello, World!</span></p><p class="c3 c5"><span class="c0 c2"></span></p><p class="c3"><span>Not surprisingly, it outputs the string "Hello, World!". Again, just say what you want and you will get it.</span></p><h2 class="c3"><a name="h.ifcjheuaxoqc"></a><span>Numbers and arithmetic operations</span></h2><p class="c3 c10"><span>Okay, so, now, you might be thinking: "What is the use of this language if it just outputs what I put in?" Of course, JSONiq can more than that. And still in a declarative way. Here is how it works with numbers:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">2 + 2</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span>will surprisingly output:</span></p><p class="c3 c9"><span class="c0 c2">4</span></p><p class="c3 c5"><span></span></p><p class="c3"><span>whereas</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">(38 + 2) div 2 + 11 * 2</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span>will output</span></p><p class="c3 c9"><span class="c0 c2">42</span></p><p class="c3 c5"><span class="c0 c2"></span></p><p class="c3 c10"><span>(mind the division operator which is the "div" keyword. The slash has other semantics).</span></p><p class="c3 c5"><span></span></p><p class="c3"><span>Like JSON, JSONiq works with decimals, too:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">6.022e23 * 42</span></p><p class="c3 c9"><span class="c0 c2">2.52924E25</span></p><h2 class="c3"><a name="h.jmbc6c1fqqwx"></a><span>Logical operations</span></h2><p class="c3 c10"><span>JSONiq supports boolean operations.</span></p><p class="c3 c10 c5"><span></span></p><p class="c3"><span class="c0">true and false</span></p><p class="c3 c9"><span class="c0 c2">false</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3"><span class="c0">(true or false) and (false or true)</span></p><p class="c3 c9"><span class="c0 c2">true</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3"><span>The unary not is a function (yes, JSONiq has functions, and they are in the same way as in many languages):</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span class="c0">not(true)</span></p><p class="c3 c9"><span class="c0 c2">false</span></p><h2 class="c3"><a name="h.iq1ixg5ywx0r"></a><span>Strings</span></h2><p class="c3"><span>JSONiq is capable of manipulating strings as well, using functions:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">concat("Hello ", "Captain Kirk")</span></p><p class="c3 c9"><span class="c0 c2">Hello Captain Kirk</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3"><span class="c0">substring("Mister Spock", 8, 5)</span></p><p class="c3 c9"><span class="c0 c2">Spock</span></p><p class="c4 c3"><span class="c2"></span></p><p class="c3 c10"><span>JSONiq comes up with a rich string function library out of the box inherited from its base language. These functions are listed </span><span class="c1"><a class="c14" href="http://www.w3.org/TR/xpath-functions-30/#string-functions">here</a></span><span> (actually, you will find even many more for numbers, etc.)</span></p><h2 class="c3"><a name="h.rv6w8p4wenfa"></a><span>Sequences</span></h2><p class="c3"><span>Until now, we only handled single values (an object, an array, a number, a string, a boolean). JSONiq supports sequences of values. You can build a sequence using commas:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span>1, 2, 3, 4, 5, 6, 7, 8, 9, 10</span></p><p class="c3 c9"><span class="c2">1 2 3 4 5 6 7 8 9 10</span></p><p class="c3 c5"><span class="c2"></span></p><p class="c3"><span class="c0">1, </span><span class="c0">true</span><span class="c0">, 4.2e1, "Life"</span></p><p class="c3 c9"><span class="c0 c2">1 true 42 Life</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span>The "to" operator is very convenient, too:</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span class="c0">1 to 100</span></p><p class="c3 c9"><span class="c2">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20</span></p><p class="c3 c9"><span class="c2">21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40</span></p><p class="c3 c9"><span class="c2">41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60</span></p><p class="c3 c9"><span class="c2">61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80</span></p><p class="c3 c9"><span class="c2">81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100</span></p><p class="c3 c5"><span></span></p><p class="c3"><span>Some functions even work on sequences:</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span class="c0">sum(1 to 100)</span></p><p class="c3 c9"><span class="c0 c2">5050</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3"><span class="c0">string-join(("These", "are", "some", "words"), "-")</span></p><p class="c3 c9"><span class="c0 c2">These-are-some-words</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3"><span class="c0">count(10 to 20)</span></p><p class="c3 c9"><span class="c0 c2">11</span></p><p class="c3 c5"><span class="c0 c2"></span></p><p class="c3"><span class="c0">avg(1 to 100)</span></p><p class="c3 c9"><span class="c0 c2">50.5</span></p><h1 class="c3"><a name="h.7x2r8sj1zjwe"></a><span>A bit more in depth</span></h1><h2 class="c3"><a name="h.b6c9zq9um8cu"></a><span>Variables</span></h2><p class="c3"><span>You can bind a sequence of values to a (dollar-prefixed) variable, like so:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">let $x := "Bearing 3 1 4 Mark 5. "</span></p><p class="c3"><span class="c0">return concat($x, "Engage!")</span></p><p class="c3 c9"><span class="c0 c2">Bearing 3 1 4 Mark 5. Engage!</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c4 c3"><span class="c0"></span></p><p class="c3"><span class="c0">let $x := ("Kirk", "Picard", "Sisko")</span></p><p class="c3"><span class="c0">return string-join($x, " and ")</span></p><p class="c3 c9"><span class="c0 c2">Kirk and Picard and Sisko</span></p><p class="c3 c5"><span class="c0 c2"></span></p><p class="c3"><span>You can bind as many variables as you want:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">let $x := 1</span></p><p class="c3"><span class="c0">let $y := $x * 2</span></p><p class="c3"><span class="c0">let $z := $y + $x</span></p><p class="c3"><span class="c0">return [$x, $y, $z]</span></p><p class="c3 c9"><span class="c0 c2">[ 1, 2, 3 ]</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3"><span>and even reuse the same name:</span></p><p class="c3"><span class="c0">let $x := 1</span></p><p class="c3"><span class="c0">let $x := $x + 2</span></p><p class="c3"><span class="c0">let $x := $x + 3</span></p><p class="c3"><span class="c0">return $x</span></p><p class="c3 c9"><span class="c0 c2">6</span></p><h2 class="c3"><a name="h.92ak2udyfghp"></a><span>Iteration</span></h2><p class="c3 c10"><span>In a way very similar to let, you can iterate over a sequence of values with the "for" keyword. Instead of binding the entire sequence of the variable, it will bind each value of the sequence in turn to this variable.</span></p><p class="c3 c10 c5"><span></span></p><p class="c3 c10"><span class="c0">for $i in 1 to 10</span></p><p class="c3 c10"><span class="c0">return $i * 2</span></p><p class="c3 c9"><span class="c0 c2">2 4 6 8 10 12 14 16 18 20</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3"><span>More interestingly, you can combine fors and lets like so:</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span class="c0">let $sequence := 1 to 10</span></p><p class="c3"><span class="c0">for $value in $sequence</span></p><p class="c3"><span class="c0">let $square := $value * 2</span></p><p class="c3"><span class="c0">return $square</span></p><p class="c3 c9"><span class="c0 c2">2 4 6 8 10 12 14 16 18 20</span></p><p class="c3 c4"><span class="c0 c2"></span></p><p class="c3"><span>and even filter out some values:</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span class="c0">let $sequence := 1 to 10</span></p><p class="c3"><span class="c0">for $value in $sequence</span></p><p class="c3"><span class="c0">let $square := $value * 2</span></p><p class="c3"><span class="c0">where $square < 10</span></p><p class="c3"><span class="c0">return $square</span></p><p class="c3 c9"><span class="c0 c2">2 4 6 8</span></p><h2 class="c3"><a name="h.zdhx60a5duyu"></a><span>Conditions</span></h2><p class="c3"><span>You can make the output depend on a condition with an if-then-else construct:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">for $x in 1 to 10</span></p><p class="c3"><span class="c0">return if ($x < 5) then $x</span></p><p class="c3"><span class="c0"> else -$x</span></p><p class="c3 c9"><span class="c0 c2">1 2 3 4 -5 -6 -7 -8 -9 -10</span></p><h2 class="c3"><a name="h.ccs6lkxiixw4"></a><span>Composability of Expressions</span></h2><p class="c3"><span>Now that you know of a couple of elementary JSONiq expressions, you can combine then in more elaborate expressions. For example, you can put any sequence of values in an array:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">[ 1 to 10 ]</span></p><p class="c3 c9"><span class="c0 c2">[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3"><span>Or you can dynamically compute the value of object pairs:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">{</span></p><p class="c3"><span class="c0"> "Greeting" : (let $d := "Mister Spock"</span></p><p class="c3"><span class="c0"> return concat("Hello, ", $d)),</span></p><p class="c3"><span class="c0"> "Farewell" : string-join(("Live", "long", "and", "prosper"),</span></p><p class="c3"><span class="c0"> " ")</span></p><p class="c3"><span class="c0">}</span></p><p class="c3 c5"><span class="c0 c2"></span></p><p class="c3 c9"><span class="c0 c2">{ "Greeting" : "Hello, Mister Spock", "Farewell" : "Live long and prosper" }</span></p><p class="c3 c5"><span class="c2"></span></p><p class="c3"><span>You can also dynamically generate object singletons (with a single pair):</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span class="c0">{ concat("Integer ", 2) : 2 * 2 }</span></p><p class="c3 c9"><span class="c0 c2">{ "Integer 2" : 4 }</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3"><span>and then merge lots of them into a new object with the {| |} notation:</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span class="c0">{|</span></p><p class="c3"><span class="c0"> for $i in 1 to 10</span></p><p class="c3"><span class="c0"> return { concat("Square of ", $i) : $i * $i }</span></p><p class="c3"><span class="c0">|}</span></p><p class="c3 c8"><span class="c0 c2">{</span></p><p class="c3 c8"><span class="c0 c2">"Square of 1" : 1,</span></p><p class="c3 c8"><span class="c0 c2">"Square of 2" : 4,</span></p><p class="c3 c8"><span class="c0 c2">"Square of 3" : 9,</span></p><p class="c3 c8"><span class="c0 c2">"Square of 4" : 16,</span></p><p class="c3 c8"><span class="c0 c2">"Square of 5" : 25,</span></p><p class="c3 c8"><span class="c0 c2">"Square of 6" : 36,</span></p><p class="c3 c8"><span class="c0 c2">"Square of 7" : 49,</span></p><p class="c3 c8"><span class="c0 c2">"Square of 8" : 64,</span></p><p class="c3 c8"><span class="c0 c2">"Square of 9" : 81,</span></p><p class="c3 c8"><span class="c0 c2">"Square of 10" : 100</span></p><p class="c3 c8"><span class="c0 c2">}</span></p><h1 class="c3"><a name="h.mjv7kyjurri2"></a><span>JSON Navigation</span></h1><p class="c3 c10"><span>Up to now, you learnt how to compose expressions so as to do some computations and to build objects and arrays. It also works the other way round: if you have some JSON data, you can access it and navigate.</span></p><p class="c3 c10 c5"><span></span></p><p class="c3 c10"><span>All you need to know is: JSONiq views</span></p><ol class="c19" start="1"><li class="c7 c3 c6"><span>an array as a sequence of values,</span></li><li class="c7 c3 c6"><span>an object as a set of name/value pairs</span></li></ol><h2 class="c3 c10"><a name="h.xosiyb17dh24"></a><span>Objects</span></h2><p class="c3 c10"><span>If you use an object as a functor and provide it with a string, it will return the value associated with its parameter:</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span class="c0">let $person := {</span></p><p class="c3"><span class="c0"> "first name" : "Sarah",</span></p><p class="c3"><span class="c0"> "age" : 13,</span></p><p class="c3"><span class="c0"> "gender" : "female",</span></p><p class="c3"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c3"><span class="c0">}</span></p><p class="c3"><span class="c0">return $person("first name")</span></p><p class="c3 c9"><span class="c0 c2">"Sarah"</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3"><span>You can also ask for all keys in an object:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">let $person := {</span></p><p class="c3"><span class="c0"> "name" : "Sarah",</span></p><p class="c3"><span class="c0"> "age" : 13,</span></p><p class="c3"><span class="c0"> "gender" : "female",</span></p><p class="c3"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c3"><span class="c0">}</span></p><p class="c3"><span class="c0">return { "keys" : [ jn:keys($person)] }</span></p><p class="c16 c4 c3"><span class="c0 c2"></span></p><p class="c3 c9 c16"><span class="c0 c2">{ "keys" : [ "name", "age", "gender", "friends" ] }</span></p><h2 class="c3"><a name="h.mrf42gizl3y6"></a><span>Arrays</span></h2><p class="c3 c10"><span>If you use an array as a functor and provide it with an integer, it will return the corresponding entry:</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3"><span class="c0">let $friends := [ "Jim", "Mary", "Jennifer"]</span></p><p class="c3"><span class="c0">return $friends(2)</span></p><p class="c3 c9"><span class="c0 c2">Mary</span></p><p class="c3 c5"><span></span></p><p class="c3"><span>It is also possible to get the size of an array:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">let $person := {</span></p><p class="c3"><span class="c0"> "name" : "Sarah",</span></p><p class="c3"><span class="c0"> "age" : 13,</span></p><p class="c3"><span class="c0"> "gender" : "female",</span></p><p class="c3"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c3"><span class="c0">}</span></p><p class="c3"><span class="c0">return { "how many friends" : jn:size($person("friends")) }</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3 c9"><span class="c0 c2">{ "how many friends" : 3 }</span></p><p class="c3 c5"><span></span></p><p class="c3"><span>For convenience, there is a function that returns all elements in an array, as a sequence:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">let $person := {</span></p><p class="c3"><span class="c0"> "name" : "Sarah",</span></p><p class="c3"><span class="c0"> "age" : 13,</span></p><p class="c3"><span class="c0"> "gender" : "female",</span></p><p class="c3"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c3"><span class="c0">}</span></p><p class="c3"><span class="c0">return jn:members($person("friends"))</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3 c9"><span class="c0 c2">Jim Mary Jennifer</span></p><p class="c4 c3"><span class="c2"></span></p><h1 class="c3"><a name="h.eb0bxle2oykl"></a><span>Relational Algebra</span></h1><p class="c3 c10"><span>Remember last century's SELECT FROM WHERE statements? Well, JSONiq didn't throw out the baby with the bathwater. It has selection, projection and join capability.</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">let $stores :=</span></p><p class="c3"><span class="c0">[</span></p><p class="c3"><span class="c0"> { "store number" : 1, "state" : "MA" },</span></p><p class="c3"><span class="c0"> { "store number" : 2, "state" : "MA" },</span></p><p class="c3"><span class="c0"> { "store number" : 3, "state" : "CA" },</span></p><p class="c3"><span class="c0"> { "store number" : 4, "state" : "CA" }</span></p><p class="c3"><span class="c0">]</span></p><p class="c3"><span class="c0">let $sales := [</span></p><p class="c3"><span class="c0"> { "product" : "broiler", "store number" : 1, "quantity" : 20 },</span></p><p class="c3"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 100 },</span></p><p class="c3"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 50 },</span></p><p class="c3"><span class="c0"> { "product" : "toaster", "store number" : 3, "quantity" : 50 },</span></p><p class="c3"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 100 },</span></p><p class="c3"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 150 },</span></p><p class="c3"><span class="c0"> { "product" : "socks", "store number" : 1, "quantity" : 500 },</span></p><p class="c3"><span class="c0"> { "product" : "socks", "store number" : 2, "quantity" : 10 },</span></p><p class="c3"><span class="c0"> { "product" : "shirt", "store number" : 3, "quantity" : 10 }</span></p><p class="c3"><span class="c0">]</span></p><p class="c3"><span class="c0">let $join :=</span></p><p class="c3"><span class="c0"> for $store in jn:members($stores), $sale in jn:members($sales)</span></p><p class="c3"><span class="c0"> where $store("store number") = $sale("store number")</span></p><p class="c3"><span class="c0"> return {</span></p><p class="c3"><span class="c0"> "nb" : $store("store number"),</span></p><p class="c3"><span class="c0"> "state" : $store("state"),</span></p><p class="c3"><span class="c0"> "sold" : $sale("product")</span></p><p class="c3"><span class="c0"> }</span></p><p class="c3"><span class="c0">return [$join]</span></p><p class="c3 c8"><span class="c0 c2">[ </span></p><p class="c3 c8"><span class="c0 c2">{ "nb" : 1, "state" : "MA", "sold" : "broiler" },</span></p><p class="c3 c8"><span class="c0 c2">{ "nb" : 1, "state" : "MA", "sold" : "socks" },</span></p><p class="c3 c8"><span class="c0 c2">{ "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c3 c8"><span class="c0 c2">{ "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c3 c8"><span class="c0 c2">{ "nb" : 2, "state" : "MA", "sold" : "socks" },</span></p><p class="c3 c8"><span class="c0 c2">{ "nb" : 3, "state" : "CA", "sold" : "toaster" },</span></p><p class="c3 c8"><span class="c0 c2">{ "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c3 c8"><span class="c0 c2">{ "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c3 c8"><span class="c0 c2">{ "nb" : 3, "state" : "CA", "sold" : "shirt" }</span></p><p class="c3 c8"><span class="c0 c2"> ]</span></p><h1 class="c3"><a name="h.oii6pvliilhi"></a><span>Access external data</span></h1><p class="c3"><span>Our implementation even supports collections of JSON objects or arrays:</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">dml:collection("my:data")</span></p><p class="c3 c9"><span class="c0 c2">{ "foo" : "Your" }</span></p><p class="c3 c9"><span class="c0 c2">{ "foo" : "Collection" }</span></p><p class="c3 c9"><span class="c0 c2">{ "foo" : "of" }</span></p><p class="c3 c9"><span class="c0 c2">{ "foo" : "JSON" }</span></p><p class="c3 c9"><span class="c0 c2">{ "foo" : "objects" }</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3"><span>It is also possible to get JSON content with an HTTP request, or by parsing it from a string. Functions that handle this are available.</span></p><h1 class="c3"><a name="h.bm3buqmzhtko"></a><span>I want more</span></h1><p class="c3 c10"><span>JSONiq supports JSON updates. You can declaratively update your JSON data. JSONiq provides updating expressions. The list of updates that is eventually output by your program is then applied to your JSON data.</span></p><p class="c3 c5"><span></span></p><p class="c3"><span class="c0">copy $people := {</span></p><p class="c3"><span class="c0"> "John" : { "status" : "single" },</span></p><p class="c3"><span class="c0"> "Mary" : { "status" : "single" } }</span></p><p class="c3"><span class="c0">modify (replace json value of $people("John")("status") with "married",</span></p><p class="c3"><span class="c0"> replace json value of $people("Mary")("status") with "married")</span></p><p class="c3"><span class="c0">return $people</span></p><p class="c3 c5"><span class="c0"></span></p><p class="c3 c9"><span class="c0 c2">{ "John" : { "status" : "married" }, "Mary" : { "status" : "married" } }</span></p><p class="c4 c3"><span class="c0 c2"></span></p><p class="c3 c10"><span>Other updates are insertion into an object or an array, replacement of a value in an object or an array, deletion in an object or an array, renaming an object pair, appending to an array.</span></p><h2 class="c3"><a name="h.5itcphr8262b"></a><span>Even more</span></h2><p class="c3"><span>JSONiq can do way more that what is presented here. Here are a couple of highlights:</span></p><p class="c3 c10"><span>- JSONiq is a strongly typed language, but is smart enough to not bother you with types when unnecessary. It potentially supports static typing as well to detect errors before you even execute your program.</span></p><p class="c3"><span>- You can define your own functions and modules.</span></p><p class="c3"><span>- JSONiq provides you with loads of available modules.</span></p><p class="c3 c10"><span>- JSONiq has tons of further features such as switch, typeswitch and try-catch expressions, universal/existential quantifiers, path expressions, filtering expressions, functors, mappings, grouping, windowing.</span></p><h2 class="c3"><a name="h.j7oh3cyhem38"></a><span>More is not enough</span></h2><p class="c3 c10"><span>- JSONiq supports XML. Yes: you can manipulate JSON and XML with the same language! JSONiq is actually a superset of XQuery, a W3C standard, and extends its data model to support JSON.</span></p><p class="c3 c10"><span>- JSONiq supports scripting. If you need to write a full-fledged, side-effecting Web application, scripting is for you.</span></p><p class="c3 c10 c5"><span></span></p><p class="c3 c10"><span>The complete JSONiq specification is available on </span><span class="c1"><a class="c14" href="http://www.jsoniq.org/">http://www.jsoniq.org/</a></span></p></body></html>
\ No newline at end of file
+<html><head><title>XQuery for JSON</title><style type="text/css">@import url('https://themes.googleusercontent.com/fonts/css?kit=lhDjYqiy3mZ0x6ROQEUoUw');ol{margin:0;padding:0}.c1{height:11pt;text-align:right;direction:ltr}.c3{color:#1155cc;text-decoration:underline;font-weight:bold}.c15{list-style-type:disc;margin:0;padding:0}.c16{max-width:468pt;background-color:#ffffff;padding:72pt 72pt 72pt 72pt}.c7{color:#ff0000;font-style:italic}.c19{text-indent:-13.5pt;margin-left:76.5pt}.c2{direction:ltr;margin-left:144pt}.c13{color:inherit;text-decoration:inherit}.c14{padding-left:0pt;margin-left:36pt}.c20{color:#1155cc;text-decoration:underline}.c17{color:#4a86e8}.c6{text-align:center}.c0{font-family:"Consolas"}.c10{font-style:italic}.c4{direction:ltr}.c9{text-align:justify}.c11{text-align:right}.c5{color:#38761d}.c18{color:#ff9900}.c12{font-weight:bold}.c8{height:11pt}.title{padding-top:24pt;line-height:1.15;text-align:center;color:#4a86e8;font-size:36pt;font-family:"Arial";font-weight:bold;padding-bottom:6pt}.subtitle{padding-top:18pt;line-height:1.15;text-align:left;color:#666666;font-style:italic;font-size:24pt;font-family:"Georgia";padding-bottom:4pt}li{color:#000000;font-size:11pt;font-family:"Arial"}p{color:#000000;font-size:11pt;margin:0;font-family:"Arial"}h1{padding-top:24pt;line-height:1.15;text-align:left;color:#4a86e8;font-size:24pt;font-family:"Arial";font-weight:bold;padding-bottom:6pt}h2{padding-top:18pt;line-height:1.15;text-align:left;color:#ff9900;font-size:18pt;font-family:"Arial";font-weight:bold;padding-bottom:4pt}h3{padding-top:14pt;line-height:1.15;text-align:left;color:#000000;font-size:14pt;font-family:"Arial";font-weight:bold;padding-bottom:4pt}h4{padding-top:12pt;line-height:1.15;text-align:left;color:#000000;font-size:12pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}h5{padding-top:11pt;line-height:1.15;text-align:left;color:#000000;font-size:11pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}h6{padding-top:10pt;line-height:1.15;text-align:left;color:#000000;font-size:10pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}</style></head><body class="c16"><p class="c4 title"><a name="h.ngvhp3svo6iy"></a><span>JSONiq for JSON users</span></p><hr><p class="c6 c4"><span>This tutorial introduces the JSONiq language, which declaratively manipulates JSON data.</span></p><p class="c6 c4"><span>Why don't you go ahead can try the queries of this document on our online demo interface?</span></p><p class="c4 c6"><span> </span><span class="c3"><a class="c13" href="http://www.zorba-xquery.com/html/jsoniq">http://www.zorba-xquery.com/html/jsoniq</a></span></p><hr><p class="c4 c8"><span></span></p><h1 class="c4"><a name="h.f453h84m2u1a"></a><span>JSON</span></h1><p class="c4 c9"><span>As explained on the official Web site </span><span class="c20"><a class="c13" href="http://www.json.org/">http://www.json.org/</a></span><span>, JSON is a lightweight data-interchange format designed for humans as well as for computers. It supports as values:</span></p><ol class="c15" start="1"><li class="c14 c4 c9"><span>objects (string-to-value maps)</span></li><li class="c4 c9 c14"><span>arrays (ordered sequences of values)</span></li><li class="c14 c4 c9"><span>strings</span></li><li class="c14 c4 c9"><span>numbers</span></li><li class="c14 c4 c9"><span>booleans (true, false)</span></li><li class="c14 c4 c9"><span>null</span></li></ol><p class="c4 c8"><span></span></p><p class="c4"><span>JSONiq provides declarative querying and updating capabilities on JSON data.</span></p><h1 class="c4"><a name="h.qtfakecy3fr7"></a><span>Elevator Pitch</span></h1><p class="c4 c9"><span>JSONiq is based on XQuery, which is a W3C standard (like XML and HTML). XQuery is a very powerful declarative language that originally manipulates XML data, but it turns out that it is also a very good fit for manipulating JSON natively.</span></p><p class="c4 c9 c8"><span></span></p><p class="c4 c9"><span>JSONiq, since it extends XQuery, is a very powerful general-purpose declarative programming language. Our experience is that, for the same task, you will probably write about 80% less code compared to imperative languages like JavaScript, Python or Ruby. Additionally, you get the benefits of strong type checking without actually having to write type declarations.</span></p><p class="c4 c9 c8"><span></span></p><p class="c4 c9"><span>Here is an appetizer before we start the tutorial from scratch.</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">let $stores :=</span></p><p class="c4"><span class="c0">[</span></p><p class="c4"><span class="c0"> { "store number" : 1, "state" : "MA" },</span></p><p class="c4"><span class="c0"> { "store number" : 2, "state" : "MA" },</span></p><p class="c4"><span class="c0"> { "store number" : 3, "state" : "CA" },</span></p><p class="c4"><span class="c0"> { "store number" : 4, "state" : "CA" }</span></p><p class="c4"><span class="c0">]</span></p><p class="c4"><span class="c0">let $sales := [</span></p><p class="c4"><span class="c0"> { "product" : "broiler", "store number" : 1, "quantity" : 20 },</span></p><p class="c4"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 100 },</span></p><p class="c4"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 50 },</span></p><p class="c4"><span class="c0"> { "product" : "toaster", "store number" : 3, "quantity" : 50 },</span></p><p class="c4"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 100 },</span></p><p class="c4"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 150 },</span></p><p class="c4"><span class="c0"> { "product" : "socks", "store number" : 1, "quantity" : 500 },</span></p><p class="c4"><span class="c0"> { "product" : "socks", "store number" : 2, "quantity" : 10 },</span></p><p class="c4"><span class="c0"> { "product" : "shirt", "store number" : 3, "quantity" : 10 }</span></p><p class="c4"><span class="c0">]</span></p><p class="c4"><span class="c0">let $join :=</span></p><p class="c4"><span class="c0"> for $store in jn:members($stores), $sale in jn:members($sales)</span></p><p class="c4"><span class="c0"> where $store("store number") = $sale("store number")</span></p><p class="c4"><span class="c0"> return {</span></p><p class="c4"><span class="c0"> "nb" : $store("store number"),</span></p><p class="c4"><span class="c0"> "state" : $store("state"),</span></p><p class="c4"><span class="c0"> "sold" : $sale("product")</span></p><p class="c4"><span class="c0"> }</span></p><p class="c4"><span class="c0">return [$join]</span></p><p class="c2"><span class="c0 c5">[ </span></p><p class="c2"><span class="c0 c5"> { "nb" : 1, "state" : "MA", "sold" : "broiler" },</span></p><p class="c2"><span class="c0 c5"> { "nb" : 1, "state" : "MA", "sold" : "socks" },</span></p><p class="c2"><span class="c0 c5"> { "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c2"><span class="c0 c5"> { "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c2"><span class="c0 c5"> { "nb" : 2, "state" : "MA", "sold" : "socks" },</span></p><p class="c2"><span class="c0 c5"> { "nb" : 3, "state" : "CA", "sold" : "toaster" },</span></p><p class="c2"><span class="c0 c5"> { "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c2"><span class="c0 c5"> { "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c2"><span class="c0 c5"> { "nb" : 3, "state" : "CA", "sold" : "shirt" }</span></p><p class="c2"><span class="c0 c5"> ]</span></p><p class="c4 c8"><span></span></p><h1 class="c4"><a name="h.yugk1mszt0re"></a><span>And here you go</span></h1><h2 class="c4"><a name="h.4uvhbej4btrt"></a><span>Actually</span><span>, you already knew some JSONiq</span></h2><p class="c4 c9"><span>The first thing you need to know is that, as a rule of thumb, a well-formed JSON document is a JSONiq expression as well.</span></p><p class="c4 c8"><span></span></p><p class="c4 c9"><span>This means that, most of the time, you can copy-and-paste a JSON document into a query. The following are JSONiq queries that are "idempotent" (they just output themselves):</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">{ "pi" : 3.14, "sq2" : 1.4 }</span></p><p class="c4 c11"><span class="c0 c5">{ "pi" : 3.14, "sq2" : 1.4 }</span></p><p class="c4 c8"><span class="c0 c5"></span></p><p class="c4"><span class="c0">[ 2, 3, 5, 7, 11, 13 ]</span></p><p class="c4 c11"><span class="c0 c5">[ 2, 3, 5, 7, 11, 13 ]</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span class="c0">{</span></p><p class="c4"><span class="c0"> "operations" : [</span></p><p class="c4"><span class="c0"> { "binary" : [ "and", "or"] },</span></p><p class="c4"><span class="c0"> { "unary" : ["not"] }</span></p><p class="c4"><span class="c0"> ],</span></p><p class="c4"><span class="c0"> "bits" : [</span></p><p class="c4"><span class="c0"> 0, 1</span></p><p class="c4"><span class="c0"> ]</span></p><p class="c4"><span class="c0">}</span></p><p class="c2"><span class="c0 c5">{</span></p><p class="c2"><span class="c0 c5"> "operations" : [</span></p><p class="c2"><span class="c0 c5"> { "binary" : [ "and", "or" ] },</span></p><p class="c2"><span class="c0 c5"> { "unary" : [ "not" ] }</span></p><p class="c2"><span class="c0 c5"> ],</span></p><p class="c2"><span class="c0 c5"> "bits" : [</span></p><p class="c2"><span class="c0 c5"> 0, 1</span></p><p class="c2"><span class="c0 c5"> ]</span></p><p class="c2"><span class="c0 c5">}</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span class="c0">[ { "Question" : "Ultimate" }, ["Life", "the universe", "and everything"] ]</span></p><p class="c1"><span class="c0"></span></p><p class="c4 c11"><span class="c0 c5">[ { "Question" : "Ultimate" }, [ "Life", "the universe", "and everything" ] ]</span></p><p class="c1"><span class="c0"></span></p><p class="c4"><span>This works with objects, arrays (even nested), strings, numbers, booleans, null. </span><span class="c10">The exceptions to this rule (but we are working on it!) are that:</span></p><p class="c4 c9"><span class="c10">(i) empty objects are not recognized and must be written {| |}.</span></p><p class="c4 c9"><span class="c10">(ii) characters escaped with the \ in JSON strings are not recognized (XQuery uses another means of escaping characters).</span></p><p class="c4 c8"><span class="c0 c7"></span></p><p class="c4 c9"><span>It also works the other way round: if your query outputs an object or an array, you can use it as a JSON document.</span></p><p class="c4 c8"><span></span></p><p class="c4 c9"><span>JSONiq is a declarative language. This means that you only need to say </span><span class="c10">what</span><span> you want - the compiler will take care of the </span><span class="c10">how</span><span>. In the above queries, you are basically saying: I want to output this JSON content, and here it is.</span></p><h1 class="c4"><a name="h.1gal1zhyffu4"></a><span>JSONiq basics</span></h1><h2 class="c4"><a name="h.ncbxtez2z3rn"></a><span>The real JSONiq Hello, World!</span></h2><p class="c4"><span>Wondering what a hello world program looks like in JSONiq? Here it is:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">"Hello, World!"</span></p><p class="c4 c11"><span class="c0 c5">Hello, World!</span></p><p class="c4 c8"><span class="c0 c5"></span></p><p class="c4"><span>Not surprisingly, it outputs the string "Hello, World!".</span></p><h2 class="c4"><a name="h.ifcjheuaxoqc"></a><span>Numbers and arithmetic operations</span></h2><p class="c4 c9"><span>Okay, so, now, you might be thinking: "What is the use of this language if it just outputs what I put in?" Of course, JSONiq can more than that. And still in a declarative way. Here is how it works with numbers:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">2 + 2</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span>will output:</span></p><p class="c4 c11"><span class="c0 c5">4</span></p><p class="c4 c8"><span></span></p><p class="c4"><span>whereas</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">(38 + 2) div 2 + 11 * 2</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span>will output</span></p><p class="c4 c11"><span class="c0 c5">42</span></p><p class="c4 c8"><span class="c0 c5"></span></p><p class="c4 c9"><span>(mind the division operator which is the "div" keyword. The slash operator has different semantics).</span></p><p class="c4 c8"><span></span></p><p class="c4"><span>Like JSON, JSONiq works with decimals and doubles:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">6.022e23 * 42</span></p><p class="c4 c11"><span class="c0 c5">2.52924E25</span></p><h2 class="c4"><a name="h.jmbc6c1fqqwx"></a><span>Logical operations</span></h2><p class="c4 c9"><span>JSONiq supports boolean operations.</span></p><p class="c4 c9 c8"><span></span></p><p class="c4"><span class="c0">true and false</span></p><p class="c4 c11"><span class="c0 c5">false</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span class="c0">(true or false) and (false or true)</span></p><p class="c4 c11"><span class="c0 c5">true</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span>The unary not is a function (yes, JSONiq has functions):</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span class="c0">not(true)</span></p><p class="c4 c11"><span class="c0 c5">false</span></p><h2 class="c4"><a name="h.iq1ixg5ywx0r"></a><span>Strings</span></h2><p class="c4"><span>JSONiq is capable of manipulating strings as well, using functions:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">concat("Hello ", "Captain ", "Kirk")</span></p><p class="c4 c11"><span class="c0 c5">Hello Captain Kirk</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span class="c0">substring("Mister Spock", 8, 5)</span></p><p class="c4 c11"><span class="c0 c5">Spock</span></p><p class="c1"><span class="c5"></span></p><p class="c4 c9"><span>JSONiq comes up with a rich string function library out of the box, inherited from its base language. These functions are listed </span><span class="c20"><a class="c13" href="http://www.w3.org/TR/xpath-functions-30/#string-functions">here</a></span><span> (actually, you will find many more for numbers, etc.)</span></p><h2 class="c4"><a name="h.rv6w8p4wenfa"></a><span>Sequences</span></h2><p class="c4"><span>Until now, we have only been working with single values (an object, an array, a number, a string, a boolean). JSONiq supports sequences of values. You can build a sequence using commas:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)</span></p><p class="c4 c11"><span class="c5">1 2 3 4 5 6 7 8 9 10</span></p><p class="c4 c8"><span class="c5"></span></p><p class="c4"><span class="c0">1, </span><span class="c0">true</span><span class="c0">, 4.2e1, "Life"</span></p><p class="c4 c11"><span class="c0 c5">1 true 42 Life</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span>The "to" operator is very convenient, too:</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span class="c0">(1 to 100)</span></p><p class="c4 c11"><span class="c5">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20</span></p><p class="c4 c11"><span class="c5">21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40</span></p><p class="c4 c11"><span class="c5">41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60</span></p><p class="c4 c11"><span class="c5">61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80</span></p><p class="c4 c11"><span class="c5">81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100</span></p><p class="c4 c8"><span></span></p><p class="c4"><span>Some functions even work on sequences:</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span class="c0">sum(1 to 100)</span></p><p class="c4 c11"><span class="c0 c5">5050</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span class="c0">string-join(("These", "are", "some", "words"), "-")</span></p><p class="c4 c11"><span class="c0 c5">These-are-some-words</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span class="c0">count(10 to 20)</span></p><p class="c4 c11"><span class="c0 c5">11</span></p><p class="c4 c8"><span class="c0 c5"></span></p><p class="c4"><span class="c0">avg(1 to 100)</span></p><p class="c4 c11"><span class="c0 c5">50.5</span></p><p class="c4 c8"><span class="c5"></span></p><p class="c4"><span>Unlike arrays, sequences are flat. The sequence (3) is identical to the integer 3, and (1, (2, 3)) is identical to (1, 2, 3).</span></p><h1 class="c4"><a name="h.7x2r8sj1zjwe"></a><span>A bit more in depth</span></h1><h2 class="c4"><a name="h.b6c9zq9um8cu"></a><span>Variables</span></h2><p class="c4"><span>You can bind a sequence of values to a (dollar-prefixed) variable, like so:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">let $x := "Bearing 3 1 4 Mark 5. "</span></p><p class="c4"><span class="c0">return concat($x, "Engage!")</span></p><p class="c4 c11"><span class="c0 c5">Bearing 3 1 4 Mark 5. Engage!</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c1"><span class="c0"></span></p><p class="c4"><span class="c0">let $x := ("Kirk", "Picard", "Sisko")</span></p><p class="c4"><span class="c0">return string-join($x, " and ")</span></p><p class="c4 c11"><span class="c0 c5">Kirk and Picard and Sisko</span></p><p class="c4 c8"><span class="c0 c5"></span></p><p class="c4"><span>You can bind as many variables as you want:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">let $x := 1</span></p><p class="c4"><span class="c0">let $y := $x * 2</span></p><p class="c4"><span class="c0">let $z := $y + $x</span></p><p class="c4"><span class="c0">return ($x, $y, $z)</span></p><p class="c4 c11"><span class="c0 c5">1 2 3</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span>and even reuse the same name to hide formerly declared variables:</span></p><p class="c4"><span class="c0">let $x := 1</span></p><p class="c4"><span class="c0">let $x := $x + 2</span></p><p class="c4"><span class="c0">let $x := $x + 3</span></p><p class="c4"><span class="c0">return $x</span></p><p class="c4 c11"><span class="c0 c5">6</span></p><h2 class="c4"><a name="h.92ak2udyfghp"></a><span>Iteration</span></h2><p class="c4 c9"><span>In a way very similar to let, you can iterate over a sequence of values with the "for" keyword. Instead of binding the entire sequence of the variable, it will bind each value of the sequence in turn to this variable.</span></p><p class="c4 c9 c8"><span></span></p><p class="c4 c9"><span class="c0">for $i in 1 to 10</span></p><p class="c4 c9"><span class="c0">return $i * 2</span></p><p class="c4 c11"><span class="c0 c5">2 4 6 8 10 12 14 16 18 20</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span>More interestingly, you can combine fors and lets like so:</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span class="c0">let $sequence := 1 to 10</span></p><p class="c4"><span class="c0">for $value in $sequence</span></p><p class="c4"><span class="c0">let $square := $value * 2</span></p><p class="c4"><span class="c0">return $square</span></p><p class="c4 c11"><span class="c0 c5">2 4 6 8 10 12 14 16 18 20</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span>and even filter out some values:</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span class="c0">let $sequence := 1 to 10</span></p><p class="c4"><span class="c0">for $value in $sequence</span></p><p class="c4"><span class="c0">let $square := $value * 2</span></p><p class="c4"><span class="c0">where $square < 10</span></p><p class="c4"><span class="c0">return $square</span></p><p class="c4 c11"><span class="c0 c5">2 4 6 8</span></p><h2 class="c4"><a name="h.5fcoouj7073u"></a><span>Note that you can only iterate over sequences, not arrays. To iterate over an array, you can obtain the sequence of its values with jn:members([1, 2, 3]).</span></h2><h2 class="c4"><a name="h.zdhx60a5duyu"></a><span>Conditions</span></h2><p class="c4"><span>You can make the output depend on a condition with an if-then-else construct:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">for $x in 1 to 10</span></p><p class="c4"><span class="c0">return if ($x < 5) then $x</span></p><p class="c4"><span class="c0"> else -$x</span></p><p class="c4 c11"><span class="c0 c5">1 2 3 4 -5 -6 -7 -8 -9 -10</span></p><p class="c4 c8"><span></span></p><p class="c4"><span>Note that the else clause is required - however, it can be the empty sequence () which is often when you need if only the then clause is relevant to you.</span></p><h2 class="c4"><a name="h.ccs6lkxiixw4"></a><span>Composability of Expressions</span></h2><p class="c4"><span>Now that you know of a couple of elementary JSONiq expressions, you can combine them in more elaborate expressions. For example, you can put any sequence of values in an array:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">[ 1 to 10 ]</span></p><p class="c4 c11"><span class="c0 c5">[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span>Or you can dynamically compute the value of object pairs (or their key):</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">{</span></p><p class="c4"><span class="c0"> "Greeting" : (let $d := "Mister Spock"</span></p><p class="c4"><span class="c0"> return concat("Hello, ", $d)),</span></p><p class="c4"><span class="c0"> "Farewell" : string-join(("Live", "long", "and", "prosper"),</span></p><p class="c4"><span class="c0"> " ")</span></p><p class="c4"><span class="c0">}</span></p><p class="c4 c8"><span class="c0 c5"></span></p><p class="c4 c11"><span class="c0 c5">{ "Greeting" : "Hello, Mister Spock", "Farewell" : "Live long and prosper" }</span></p><p class="c4 c8"><span class="c5"></span></p><p class="c4"><span>You can dynamically generate object singletons (with a single pair):</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span class="c0">{ concat("Integer ", 2) : 2 * 2 }</span></p><p class="c4 c11"><span class="c0 c5">{ "Integer 2" : 4 }</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span>and then merge lots of them into a new object with the {| |} notation:</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span class="c0">{|</span></p><p class="c4"><span class="c0"> for $i in 1 to 10</span></p><p class="c4"><span class="c0"> return { concat("Square of ", $i) : $i * $i }</span></p><p class="c4"><span class="c0">|}</span></p><p class="c2"><span class="c0 c5">{</span></p><p class="c2"><span class="c0 c5">"Square of 1" : 1,</span></p><p class="c2"><span class="c0 c5">"Square of 2" : 4,</span></p><p class="c2"><span class="c0 c5">"Square of 3" : 9,</span></p><p class="c2"><span class="c0 c5">"Square of 4" : 16,</span></p><p class="c2"><span class="c0 c5">"Square of 5" : 25,</span></p><p class="c2"><span class="c0 c5">"Square of 6" : 36,</span></p><p class="c2"><span class="c0 c5">"Square of 7" : 49,</span></p><p class="c2"><span class="c0 c5">"Square of 8" : 64,</span></p><p class="c2"><span class="c0 c5">"Square of 9" : 81,</span></p><p class="c2"><span class="c0 c5">"Square of 10" : 100</span></p><p class="c2"><span class="c0 c5">}</span></p><h1 class="c4"><a name="h.mjv7kyjurri2"></a><span>JSON Navigation</span></h1><p class="c4 c9"><span>Up to now, you have learnt how to compose expressions so as to do some computations and to build objects and arrays. It also works the other way round: if you have some JSON data, you can access it and navigate.</span></p><p class="c4 c9 c8"><span></span></p><p class="c4 c9"><span>All you need to know is: JSONiq views</span></p><ol class="c15" start="1"><li class="c14 c4 c9"><span>an array as an ordered list of values,</span></li><li class="c14 c4 c9"><span>an object as a set of name/value pairs</span></li></ol><h2 class="c4 c9"><a name="h.xosiyb17dh24"></a><span>Objects</span></h2><p class="c4 c9"><span>You can use an object as if it were a function and pass the call an argument of type xs:string. It will return the value associated thereto:</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span class="c0">let $person := {</span></p><p class="c4"><span class="c0"> "first name" : "Sarah",</span></p><p class="c4"><span class="c0"> "age" : 13,</span></p><p class="c4"><span class="c0"> "gender" : "female",</span></p><p class="c4"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c4"><span class="c0">}</span></p><p class="c4"><span class="c0">return $person("first name")</span></p><p class="c4 c11"><span class="c0 c5">"Sarah"</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span>You can also ask for all keys in an object:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">let $person := {</span></p><p class="c4"><span class="c0"> "name" : "Sarah",</span></p><p class="c4"><span class="c0"> "age" : 13,</span></p><p class="c4"><span class="c0"> "gender" : "female",</span></p><p class="c4"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c4"><span class="c0">}</span></p><p class="c4"><span class="c0">return { "keys" : [ jn:keys($person)] }</span></p><p class="c1 c19"><span class="c0 c5"></span></p><p class="c4 c11 c19"><span class="c0 c5">{ "keys" : [ "name", "age", "gender", "friends" ] }</span></p><h2 class="c4"><a name="h.mrf42gizl3y6"></a><span>Arrays</span></h2><p class="c4 c9"><span>You can use an array as if it were a function and pass the call an argument of type xs:integer. It will return the entry at that position:</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4"><span class="c0">let $friends := [ "Jim", "Mary", "Jennifer"]</span></p><p class="c4"><span class="c0">return $friends(2)</span></p><p class="c4 c11"><span class="c0 c5">Mary</span></p><p class="c4 c8"><span></span></p><p class="c4"><span>It is also possible to get the size of an array:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">let $person := {</span></p><p class="c4"><span class="c0"> "name" : "Sarah",</span></p><p class="c4"><span class="c0"> "age" : 13,</span></p><p class="c4"><span class="c0"> "gender" : "female",</span></p><p class="c4"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c4"><span class="c0">}</span></p><p class="c4"><span class="c0">return { "how many friends" : jn:size($person("friends")) }</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4 c11"><span class="c0 c5">{ "how many friends" : 3 }</span></p><p class="c4 c8"><span></span></p><p class="c4"><span>For convenience, there is a function that returns all elements in an array, as a sequence:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">let $person := {</span></p><p class="c4"><span class="c0"> "name" : "Sarah",</span></p><p class="c4"><span class="c0"> "age" : 13,</span></p><p class="c4"><span class="c0"> "gender" : "female",</span></p><p class="c4"><span class="c0"> "friends" : [ "Jim", "Mary", "Jennifer"]</span></p><p class="c4"><span class="c0">}</span></p><p class="c4"><span class="c0">return jn:members($person("friends"))</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4 c11"><span class="c0 c5">Jim Mary Jennifer</span></p><p class="c1"><span class="c5"></span></p><h1 class="c4"><a name="h.eb0bxle2oykl"></a><span>Relational Algebra</span></h1><p class="c4 c9"><span>Do you r</span><span>emember SQL's SELECT FROM WHERE statements? JSONiq inherits selection, projection and join capability from XQuery, too.</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">let $stores :=</span></p><p class="c4"><span class="c0">[</span></p><p class="c4"><span class="c0"> { "store number" : 1, "state" : "MA" },</span></p><p class="c4"><span class="c0"> { "store number" : 2, "state" : "MA" },</span></p><p class="c4"><span class="c0"> { "store number" : 3, "state" : "CA" },</span></p><p class="c4"><span class="c0"> { "store number" : 4, "state" : "CA" }</span></p><p class="c4"><span class="c0">]</span></p><p class="c4"><span class="c0">let $sales := [</span></p><p class="c4"><span class="c0"> { "product" : "broiler", "store number" : 1, "quantity" : 20 },</span></p><p class="c4"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 100 },</span></p><p class="c4"><span class="c0"> { "product" : "toaster", "store number" : 2, "quantity" : 50 },</span></p><p class="c4"><span class="c0"> { "product" : "toaster", "store number" : 3, "quantity" : 50 },</span></p><p class="c4"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 100 },</span></p><p class="c4"><span class="c0"> { "product" : "blender", "store number" : 3, "quantity" : 150 },</span></p><p class="c4"><span class="c0"> { "product" : "socks", "store number" : 1, "quantity" : 500 },</span></p><p class="c4"><span class="c0"> { "product" : "socks", "store number" : 2, "quantity" : 10 },</span></p><p class="c4"><span class="c0"> { "product" : "shirt", "store number" : 3, "quantity" : 10 }</span></p><p class="c4"><span class="c0">]</span></p><p class="c4"><span class="c0">let $join :=</span></p><p class="c4"><span class="c0"> for $store in jn:members($stores), $sale in jn:members($sales)</span></p><p class="c4"><span class="c0"> where $store("store number") = $sale("store number")</span></p><p class="c4"><span class="c0"> return {</span></p><p class="c4"><span class="c0"> "nb" : $store("store number"),</span></p><p class="c4"><span class="c0"> "state" : $store("state"),</span></p><p class="c4"><span class="c0"> "sold" : $sale("product")</span></p><p class="c4"><span class="c0"> }</span></p><p class="c4"><span class="c0">return [$join]</span></p><p class="c2"><span class="c0 c5">[ </span></p><p class="c2"><span class="c0 c5">{ "nb" : 1, "state" : "MA", "sold" : "broiler" },</span></p><p class="c2"><span class="c0 c5">{ "nb" : 1, "state" : "MA", "sold" : "socks" },</span></p><p class="c2"><span class="c0 c5">{ "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c2"><span class="c0 c5">{ "nb" : 2, "state" : "MA", "sold" : "toaster" },</span></p><p class="c2"><span class="c0 c5">{ "nb" : 2, "state" : "MA", "sold" : "socks" },</span></p><p class="c2"><span class="c0 c5">{ "nb" : 3, "state" : "CA", "sold" : "toaster" },</span></p><p class="c2"><span class="c0 c5">{ "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c2"><span class="c0 c5">{ "nb" : 3, "state" : "CA", "sold" : "blender" },</span></p><p class="c2"><span class="c0 c5">{ "nb" : 3, "state" : "CA", "sold" : "shirt" }</span></p><p class="c2"><span class="c0 c5"> ]</span></p><h1 class="c4"><a name="h.oii6pvliilhi"></a><span>Access external data</span></h1><p class="c4"><span>Our implementation supports collections of (and indices on) JSON objects or arrays:</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">dml:collection("my:data")</span></p><p class="c4 c11"><span class="c0 c5">{ "foo" : "Your" }</span></p><p class="c4 c11"><span class="c0 c5">{ "foo" : "Collection" }</span></p><p class="c4 c11"><span class="c0 c5">{ "foo" : "of" }</span></p><p class="c4 c11"><span class="c0 c5">{ "foo" : "JSON" }</span></p><p class="c4 c11"><span class="c0 c5">{ "foo" : "objects" }</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4"><span>It is also possible to get JSON content with an HTTP request, or by parsing it from a string. The EXPath http-client module (described in the Zorba documentation) allows you to make HTTP requests, and the jn:parse-json() function allows you to use the body as an object or an array.</span></p><h1 class="c4"><a name="h.bm3buqmzhtko"></a><span>I want more</span></h1><p class="c4 c9"><span>JSONiq supports JSON updates. You can declaratively update your JSON data. JSONiq provides updating expressions. The list of updates that is eventually output by your program is then applied to your JSON data.</span></p><p class="c4 c8"><span></span></p><p class="c4"><span class="c0">copy $people := {</span></p><p class="c4"><span class="c0"> "John" : { "status" : "single" },</span></p><p class="c4"><span class="c0"> "Mary" : { "status" : "single" } }</span></p><p class="c4"><span class="c0">modify (replace json value of $people("John")("status") with "married",</span></p><p class="c4"><span class="c0"> replace json value of $people("Mary")("status") with "married")</span></p><p class="c4"><span class="c0">return $people</span></p><p class="c4 c8"><span class="c0"></span></p><p class="c4 c11"><span class="c0 c5">{ "John" : { "status" : "married" }, "Mary" : { "status" : "married" } }</span></p><p class="c1"><span class="c0 c5"></span></p><p class="c4 c9"><span>Other updates are insertion into an object or an array, replacement of a value in an object or an array, deletion in an object or an array, renaming an object pair, appending to an array. This is documented on jsoniq.org.</span></p><h2 class="c4"><a name="h.5itcphr8262b"></a><span>Even more</span></h2><p class="c4"><span>JSONiq can do way more that what is presented here. Here are a couple of highlights:</span></p><p class="c4 c9"><span>- JSONiq is a strongly typed language, but is smart enough to not bother you with types when unnecessary. It potentially supports static typing as well to detect errors before you even execute your program.</span></p><p class="c4"><span>- You can define your own functions and modules.</span></p><p class="c4"><span>- JSONiq provides you with loads of available modules shipped with Zorba.</span></p><p class="c4 c9"><span>- JSONiq has tons of further features such as switch, typeswitch and try-catch expressions, universal/existential quantifiers, path expressions, filtering expressions, functors, mappings, grouping, windowing.</span></p><h2 class="c4"><a name="h.j7oh3cyhem38"></a><span>More is not enough</span></h2><p class="c4 c9"><span>- JSONiq supports XML. Yes: you can manipulate JSON and XML with the same language! JSONiq is actually a superset of XQuery, a W3C standard, and extends its data model to support JSON.</span></p><p class="c4 c9"><span>- JSONiq supports scripting. If you need to write a full-fledged, side-effecting Web application, scripting is for you.</span></p><p class="c4 c9 c8"><span></span></p><p class="c4 c9"><span>The complete JSONiq specification is available on </span><span class="c20"><a class="c13" href="http://www.jsoniq.org/">http://www.jsoniq.org/</a></span></p></body></html>
\ No newline at end of file
Follow ups
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: noreply, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Zorba Build Bot, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Ghislain Fourny, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Ghislain Fourny, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Ghislain Fourny, 2012-09-05
-
[Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Matthias Brantner, 2012-09-03
-
Re: [Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: William Candillon, 2012-09-03
-
Re: [Merge] lp:~zorba-coders/zorba/updated-jsoniq-tutorials into lp:zorba
From: Matthias Brantner, 2012-08-29