Search code examples
jsonxmlxqueryjsoniq

What are the differences between JSONiq and XQuery 3.1?


Both JSONiq and XQuery 3.1 extend XQuery 3.0 with support for JSON.

How do they differ?


Solution

  • Overall motivation

    XQuery 3.1 was designed with the goal to support additional data structures (maps, arrays) in memory. These structures are mapped to JSON for input and output. XQuery 3.1 has been a W3C recommendation since March 2017.

    JSONiq was designed with the goal of querying and updating JSON in settings such as document stores. It was also designed by members of the XML Query working group (disclaimer: I am one of them) while investigating various possibilities to support JSON. While it is not an official recommendation, it is stable and public.

    Data model

    Both XQuery 3.1 and JSONiq extend the data model with objects and arrays, but do so in different ways, motivated by their distinct focuses. Overall, XQuery 3.1 has a more generic data model, while JSONiq restricts it to mirror JSON.

    In JSONiq, object keys must be strings. In XQuery 3.1, they can be any atomic value.

    In JSONiq, values in objects and arrays must be single items, in particular, arrays are homomorphic to sequences even though they are distinct. In XQuery 3.1, values in object and arrays can be sequences of items.

    In JSONiq, nulls are represented with a dedicated atomic type. In XQuery 3.1, they are represented with empty sequences (which are accepted values in the data model).

    In XQuery 3.1, values are not copied with populating an array or map, which supports among others building indices on XML nodes. In JSONiq, copies are made similarly to XML constructors, to ensure a strict tree semantics.

    Construction

    The syntax for constructing objects and arrays in JSONiq is a superset of JSON.

    { "foo" : [ 1 to 10 ] }
    

    In XQuery 3.1, it is similar to computed XML node constructors:

    map { "foo" : array { 1 to 10 } }
    

    XQuery 3.1 has an alternate syntax for arrays in which commas delimite the slots for the values, to nest sequences:

    [ 1, (1 to 10), 11 ]
    

    Navigation

    XQuery 3.1 uses function calls to perform lookups in objects and arrays:

    let $map := map { "foo" : "bar" }
    return $map("foo")
    
    let $array := array { 1, 2, 3 }
    return $array(2)
    

    It also uses ? as a shortcut for unquoted names and integers:

    let $map := map { "foo" : "bar" }
    return $map?foo
    
    let $array := array { 1, 2, 3 }
    return $array?2
    
    let $array := array { 1, 2, 3 }
    return $array?*
    

    JSONiq (the core language) uses dots and square brackets

    let $map := { "foo" : "bar" }
    return $map.foo
    
    let $array := [ 1, 2, 3 ]
    return $array[[2]]
    
    let $array := [ 1, 2, 3 ]
    return $array[]
    

    (JSONiq also exists as an extension to XQuery that also overloads the function call syntax).