Rebol3 Code Examplex


JSON pointer

Navigate JSON documents using pointer syntax.

Rebol [
    title: "Rosetta code: JSON pointer"
    file:  %JSON_pointer.r3
    url:   https://rosettacode.org/wiki/JSON_pointer
]

get-json-pointer: function[
    data [map!]   "Decoded JSON data"
    ptr [string!] "JSON pointer"
][
    if empty? ptr    [return data]
    if ptr   ==  "/" [return select data ""] 
    if ptr/1 != #"/" [do to error! "Invalid JSON pointer!"]
    parts: split next ptr #"/"
    forall parts [
        parse parts/1 [any [to #"~" [
            change "~1" #"/" |
            change "~0" #"~" | skip
        ]]]
        any [
            attempt [change parts to word! parts/1]
            attempt [change parts 1 + to integer! parts/1]
        ]
    ]
    insert parts 'data
    get as path! parts 
]


data: decode 'json {{
  "wiki": {
    "links": [
      "https://rosettacode.org/wiki/Rosetta_Code",
      "https://discord.com/channels/1011262808001880065"
    ]
  },
  "": "Rosetta",
  " ": "Code",
  "g/h": "chrestomathy",
  "i~j": "site",
  "abc": ["is", "a"],
  "def": { "": "programming" }
}}

foreach ptr [
    "" "/" "/ " "/abc" "/def/" "/g~1h" "/i~0j"
    "/wiki/links/0" "/wiki/links/1" "/wiki/links/2"
    "/wiki/name" "/no/such/thing" "bad/pointer"
][
    printf [20 "--> "][
        mold ptr
        try/with [mold get-json-pointer data :ptr][ as-red "error!" ]
    ]
]

Output:

""                  --> #[
    wiki: #[
        links: ["https://rosettacode.org/wiki/Rosetta_Code" "https://discord.com/channels/1011262808001880065"]
    ]
    "" "Rosetta"
    " " "Code"
    "g/h" "chrestomathy"
    i~j: "site"
    abc: ["is" "a"]
    def: #[
        "" "programming"
    ]
]
"/"                 --> "Rosetta"
"/ "                --> "Code"
"/abc"              --> ["is" "a"]
"/def/"             --> "programming"
"/g~1h"             --> "chrestomathy"
"/i~0j"             --> "site"
"/wiki/links/0"     --> "https://rosettacode.org/wiki/Rosetta_Code"
"/wiki/links/1"     --> "https://discord.com/channels/1011262808001880065"
"/wiki/links/2"     --> _
"/wiki/name"        --> _
"/no/such/thing"    --> error!
"bad/pointer"       --> error!