JSON

From Rosetta Code
Jump to: navigation, search
Task
JSON
You are encouraged to solve this task according to the task description, using any language you may know.

Load a JSON string into a data structure. Also create a new data structure and serialize it into JSON. Use objects and arrays (as appropriate for your language) and make sure your JSON is valid (http://www.jsonlint.com/).


Contents

[edit] Ada

[edit] Alternative using GNATCOLL

 
with Ada.Text_IO;
with GNATCOLL.JSON;
 
procedure JSON_Test is
use Ada.Text_IO;
use GNATCOLL.JSON;
 
JSON_String : constant String := "{""name"":""Pingu"",""born"":1986}";
 
Penguin : JSON_Value := Create_Object;
Parents : JSON_Array;
begin
Penguin.Set_Field (Field_Name => "name",
Field => "Linux");
 
Penguin.Set_Field (Field_Name => "born",
Field => 1992);
 
Append (Parents, Create ("Linus Torvalds"));
Append (Parents, Create ("Alan Cox"));
Append (Parents, Create ("Greg Kroah-Hartman"));
 
Penguin.Set_Field (Field_Name => "parents",
Field => Parents);
 
Put_Line (Penguin.Write);
 
Penguin := Read (JSON_String, "json.errors");
 
Penguin.Set_Field (Field_Name => "born",
Field => 1986);
 
Parents := Empty_Array;
Append (Parents, Create ("Otmar Gutmann"));
Append (Parents, Create ("Silvio Mazzola"));
 
Penguin.Set_Field (Field_Name => "parents",
Field => Parents);
 
Put_Line (Penguin.Write);
end JSON_Test;
 

Output:

{"parents":["Linus Torvalds", "Alan Cox", "Greg Kroah-Hartman"], "name":"Linux", "born":1992}
{"parents":["Otmar Gutmann", "Silvio Mazzola"], "name":"Pingu", "born":1986}

[edit] Alternative using Matreshka

 
with Ada.Wide_Wide_Text_IO; use Ada.Wide_Wide_Text_IO;
with League.JSON.Arrays; use League.JSON.Arrays;
with League.JSON.Documents; use League.JSON.Documents;
with League.JSON.Objects; use League.JSON.Objects;
with League.JSON.Values; use League.JSON.Values;
with League.Strings; use League.Strings;
 
procedure Main is
 
function "+" (Item : Wide_Wide_String) return Universal_String
renames To_Universal_String;
 
JSON_String : constant Universal_String
 := +"{""name"":""Pingu"",""born"":1986}";
 
Penguin : JSON_Object;
Parents : JSON_Array;
 
begin
Penguin.Insert (+"name", To_JSON_Value (+"Linux"));
Penguin.Insert (+"born", To_JSON_Value (1992));
 
Parents.Append (To_JSON_Value (+"Linus Torvalds"));
Parents.Append (To_JSON_Value (+"Alan Cox"));
Parents.Append (To_JSON_Value (+"Greg Kroah-Hartman"));
 
Penguin.Insert (+"parents", To_JSON_Value (Parents));
 
Put_Line (To_JSON_Document (Penguin).To_JSON.To_Wide_Wide_String);
 
Penguin := From_JSON (JSON_String).To_Object;
 
Parents := Empty_JSON_Array;
 
Parents.Append (To_JSON_Value (+"Otmar Gutmann"));
Parents.Append (To_JSON_Value (+"Silvio Mazzola"));
 
Penguin.Insert (+"parents", To_JSON_Value (Parents));
 
Put_Line (To_JSON_Document (Penguin).To_JSON.To_Wide_Wide_String);
end Main;
 

Output:

{"parents":["Linus Torvalds","Alan Cox","Greg Kroah-Hartman"],"name":"Linux","born":1992}
{"parents":["Otmar Gutmann","Silvio Mazzola"],"name":"Pingu","born":1986}

[edit] ANTLR

ANTLR
ANTLR
ANTLR
ANTLR
ANTLR
ANTLR
ANTLR


[edit] Java

 
// Parse JSON
//
// Nigel Galloway - April 27th., 2012
//
grammar JSON ;
@members {
String Indent = "";
}
Number : (('0')|('-'? ('1'..'9') ('0'..'9')*)) ('.' ('0'..'9')+)? (('e'|'E') ('+'|'-')? ('0'..'9')+)?;
WS : (' ' | '\t' | '\r' |'\n') {skip();};
Tz : ' ' .. '!' | '#' .. '[' | ']' .. '~';
Control : '\\' ('"'|'\\'|'/'|'b'|'f'|'n'|'r'|'t'|UCode);
UCode : 'u' ('0'..'9'|'a'..'f'|'A'..'F') ('0'..'9'|'a'..'f'|'A'..'F') ('0'..'9'|'a'..'f'|'A'..'F') ('0'..'9'|'a'..'f'|'A'..'F');
Keyword : 'true' | 'false' | 'null';
String : '"' (Control? Tz)* '"';
object : '{' {System.out.println(Indent + "{Object}"); Indent += " ";} (pair (',' pair*)*)? '}' {Indent = Indent.substring(4);};
pair : e = String {System.out.println(Indent + "{Property}\t" + $e.text);} ':' value;
value : Number {System.out.println(Indent + "{Number} \t" + $Number.text);}
| object
| String {System.out.println(Indent + "{String} \t" + $String.text);}
| Keyword {System.out.println(Indent + "{Keyword} \t" + $Keyword.text);}
| array;
array : '[' {System.out.println(Indent + "Array"); Indent += " ";} (value (',' value)*)? ']' {Indent = Indent.substring(4);};
 

Produces:

>java Test
{
  "Nigel"
  :
  -110.2e-13
  ,
  "Fred"
  :
  {
    "Joe"
    :
    [3,true,"Nigel"]
  }
  "Harry"
  :
  [23,"Hello"]
}
^Z
{Object}
    {Property}  "Nigel"
    {Number}    -110.2e-13
    {Property}  "Fred"
    {Object}
        {Property}      "Joe"
        Array
            {Number}    3
            {Keyword}   true
            {String}    "Nigel"
    {Property}  "Harry"
    Array
        {Number}        23
        {String}        "Hello"

[edit] Bracmat

Bracmat has built-in functionality for reading and writing JSON data. A full roundtrip from JSON file over a Bracmat internal representation back to a JSON file looks like this:

put$(jsn$(get$("input.json",JSN)),"output.JSN,NEW)

Let us split this into separate steps.

To read a JSON file "myfile.json", use

get$("myfile.json",JSN)

If the JSON data, e.g, an array, has to be read from a string value, use the MEM option on the get function, like this:

get$("[1,2,3]",JSN,MEM)

To convert the corresponding Bracmat data structure (,1 2 3) back to a JSON string, use

jsn$(,1 2 3)

To write a JSON string "[1,2,3]" to a file "array.json", use

put$("[1,2,3]","array.json",NEW)

Bracmat and JSON/Javascript do far from represent data in similar ways. Bracmat has arbitrary-precision arithmetic. Floating point numbers are not a native datatype in Bracmat. Bracmat has no Boolean values true and false and no null value. Bracmat has arrays and objects, but they are second class citizens. Most data is best represented as binary tree structures, with binary operators like the plus, comma, dot or white space sitting in the nodes and the atomic parts of the data sitting in the leaves. The only data type that is somewhat the same in JSON/JavaScript and Bracmat is the string, but there is a slight difference in the representation of strings in code. Whereas strings in JSON always are enclosed in quotation marks, this is only necessary in Bracmat if a string contains operator characters or starts with flag characters.

Here are the mapping rules:

Bracmat representation JSON representation Comment
null null
true true
false false
12345 12345
2/3 6.66666666666666666667E-1 Most rational numbers cannot be represented as floating point numbers, see note (1)
(.string) "string"
(,1 2) [1,2]
((a.1)+(b.2),) {"a":1,"b":2} The + operator sorts its arguments. See note (2)

Note (1) All floating point numbers can be represented as rational numbers. Therefore, a round trip of a Bracmat number to a JSON number and back to a Bracmat number can give a different number: 2/3 becomes 666666666666666666667/1000000000000000000000.

Note (2) The objects {"a":1,"b":2} and {"b":2,"a":1} are equivalent in Bracmat, as they are both internally represented as ((a.1)+(b.2),)

Here is a full round trip of the following JSON data, which is assumed to be stored in a file "rosetta.json". The employed code is:

 
( get$("rosetta.json",JSN):?json
& lst$(json,"json.bra",NEW)
& put$(jsn$!json,"rosetta-roundtrip.json",NEW)
)

rosetta.json:

[   
    {
        "ape": "\"King Kong\"",
        "C:\\projects": "23",
        "OS\/2": {
            "White\b\f\n\r\tspace": {}
        },
        "Cyrillic": [
            "Ya \u042F",
            "ya \u044f"
        ]
    },
    "TAB	",
    [
        "elem1",
        "elem2"
    ],
    "Bernhard",
    [],
    [
        "x",
        "y",
        "z"
    ],
    [
        "true",
        true,
        false,
        null
    ],
    { 
        "fixed point": [
            3.4,
            0.00987654321,
            -10.01,
            56.78,
            56.780
        ]
    },
    {
        "floating point": [
            0e0,
            0.0000006e-007,
            17E123,
            -17.87E123,
            0.87E123,            
            286e400
        ]
    },
    {
        "integer": [
            -0,
            0,
            -5,
            1234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567890
        ]
    }
]

Content of json.bra:

json=
  
,   (   ("C:\\projects"..23)
      + (Cyrillic.,(."Ya Я") (."ya я"))
      + (OS/2.("White\b\f
\r	space".0,),)
      + (ape.."\"King Kong\"")
    , 
    )
    (.TAB\t)
    (,(.elem1) (.elem2))
    (.Bernhard)
    (,)
    (,(.x) (.y) (.z))
    (,(.true) true false null)
    ( ("fixed point".,34/10 987654321/100000000000 -1001/100 5678/100 56780/1000)
    , 
    )
    ( ( "floating point"
      .   
        ,   0
            6/100000000000000
            17000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
            -17870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
            870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
            2860000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ...
      )
    , 
    )
    ( ( integer
      .   
        ,   -0
            0
            -5
            1234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891 ...
      )
    , 
    );

The file "rosetta-roundtrip.json" will contain a single line. There is no beautify option when constructing a JSON string using the jsn function. The http://jsonlint.com service can be used to view the JSON string, but notice that some of the numbers are to big to be handled by this service and are turned into null values.

Content of rosetta-roundtrip.json (1402 characters):

[{"C:\\projects":"23","Cyrillic":["Ya Я","ya я"],"OS/2":{"White\b\f\n\r\tspace":{}},"ape":"\"King Kong\""},"TAB\t",["elem1","elem2"],"Bernhard",[],["x","y","z"],["true",true,false,null],{"fixed point":[3.4,0.00987654321,-10.01,56.78,56.78]},{"floating point":[0,0.00000000000006,17000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,-17870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,2860000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]},{"integer":[-0,0,-5,1234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567890]}]

After manual reformatting, again shortened where lines run off the screen:

[
    {
        "C:\\projects": "23",
        "Cyrillic": [
            "Ya Я",
            "ya я"
        ],
        "OS/2": {
            "White\b\f\n\r\tspace": {}
        },
        "ape": "\"King Kong\""
    },
    "TAB\t",
    [
        "elem1",
        "elem2"
    ],
    "Bernhard",
    [],
    [
        "x",
        "y",
        "z"
    ],
    [
        "true",
        true,
        false,
        null
    ],
    {
        "fixed point": [
            3.4,
            0.00987654321,
            -10.01,
            56.78,
            56.78
        ]
    },
    {
        "floating point": [
            0,
            0.00000000000006,
            17000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
            -17870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
            870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
            2860000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ...
        ]
    },
    {
        "integer": [
            -0,
            0,
            -5,
            1234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891 ...
        ]
    }
]

[edit] C

Library: YAJL
Works with: YAJL version 2

Reads a snippet of JSON into YAJL's tree format, then walks the tree to print it back out again. The tree contains numbers both in an unparsed, string form, and also converted to long long or double when possible. The example below demonstrates both ways of dealing with numbers.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <yajl/yajl_tree.h>
#include <yajl/yajl_gen.h>
 
static void print_callback (void *ctx, const char *str, size_t len)
{
FILE *f = (FILE *) ctx;
fwrite (str, 1, len, f);
}
 
static void check_status (yajl_gen_status status)
{
if (status != yajl_gen_status_ok)
{
fprintf (stderr, "yajl_gen_status was %d\n", (int) status);
exit (EXIT_FAILURE);
}
}
 
static void serialize_value (yajl_gen gen, yajl_val val, int parse_numbers)
{
size_t i;
 
switch (val->type)
{
case yajl_t_string:
check_status (yajl_gen_string (gen,
(const unsigned char *) val->u.string,
strlen (val->u.string)));
break;
case yajl_t_number:
if (parse_numbers && YAJL_IS_INTEGER (val))
check_status (yajl_gen_integer (gen, YAJL_GET_INTEGER (val)));
else if (parse_numbers && YAJL_IS_DOUBLE (val))
check_status (yajl_gen_double (gen, YAJL_GET_DOUBLE (val)));
else
check_status (yajl_gen_number (gen, YAJL_GET_NUMBER (val),
strlen (YAJL_GET_NUMBER (val))));
break;
case yajl_t_object:
check_status (yajl_gen_map_open (gen));
for (i = 0 ; i < val->u.object.len ; i++)
{
check_status (yajl_gen_string (gen,
(const unsigned char *) val->u.object.keys[i],
strlen (val->u.object.keys[i])));
serialize_value (gen, val->u.object.values[i], parse_numbers);
}
check_status (yajl_gen_map_close (gen));
break;
case yajl_t_array:
check_status (yajl_gen_array_open (gen));
for (i = 0 ; i < val->u.array.len ; i++)
serialize_value (gen, val->u.array.values[i], parse_numbers);
check_status (yajl_gen_array_close (gen));
break;
case yajl_t_true:
check_status (yajl_gen_bool (gen, 1));
break;
case yajl_t_false:
check_status (yajl_gen_bool (gen, 0));
break;
case yajl_t_null:
check_status (yajl_gen_null (gen));
break;
default:
fprintf (stderr, "unexpectedly got type %d\n", (int) val->type);
exit (EXIT_FAILURE);
}
}
 
static void print_tree (FILE *f, yajl_val tree, int parse_numbers)
{
yajl_gen gen;
 
gen = yajl_gen_alloc (NULL);
if (! gen)
{
fprintf (stderr, "yajl_gen_alloc failed\n");
exit (EXIT_FAILURE);
}
 
if (0 == yajl_gen_config (gen, yajl_gen_beautify, 1) ||
0 == yajl_gen_config (gen, yajl_gen_validate_utf8, 1) ||
0 == yajl_gen_config (gen, yajl_gen_print_callback, print_callback, f))
{
fprintf (stderr, "yajl_gen_config failed\n");
exit (EXIT_FAILURE);
}
 
serialize_value (gen, tree, parse_numbers);
yajl_gen_free (gen);
}
 
int main (int argc, char **argv)
{
char err_buf[200];
const char *json =
"{\"pi\": 3.14, \"large number\": 123456789123456789123456789, "
"\"an array\": [-1, true, false, null, \"foo\"]}";
yajl_val tree;
 
tree = yajl_tree_parse (json, err_buf, sizeof (err_buf));
if (! tree)
{
fprintf (stderr, "parsing failed because: %s\n", err_buf);
return EXIT_FAILURE;
}
 
printf ("Treating numbers as strings...\n");
print_tree (stdout, tree, 0);
printf ("Parsing numbers to long long or double...\n");
print_tree (stdout, tree, 1);
 
yajl_tree_free (tree);
 
return EXIT_SUCCESS;
}

Output:

Treating numbers as strings...
{
    "pi": 3.14,
    "large number": 123456789123456789123456789,
    "an array": [
        -1,
        true,
        false,
        null,
        "foo"
    ]
}
Parsing numbers to long long or double...
{
    "pi": 3.1400000000000001243,
    "large number": 1.2345678912345679134e+26,
    "an array": [
        -1,
        true,
        false,
        null,
        "foo"
    ]
}

[edit] C++

Library: U++
#include "Core/Core.h"
 
using namespace Upp;
 
CONSOLE_APP_MAIN
{
JsonArray a;
a << Json("name", "John")("phone", "1234567") << Json("name", "Susan")("phone", "654321");
String txt = ~a;
Cout() << txt << '\n';
Value v = ParseJSON(txt);
for(int i = 0; i < v.GetCount(); i++)
Cout() << v[i]["name"] << ' ' << v[i]["phone"] << '\n';
}
 

[edit] C#

Works with: C sharp version 3.0

This uses the JavaScriptSerializer class which was shipped with .NET 3.5.

using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;
 
class Program
{
static void Main()
{
var people = new Dictionary<string, object> {{"1", "John"}, {"2", "Susan"}};
var serializer = new JavaScriptSerializer();
 
var json = serializer.Serialize(people);
Console.WriteLine(json);
 
var deserialized = serializer.Deserialize<Dictionary<string, object>>(json);
Console.WriteLine(deserialized["2"]);
 
var jsonObject = serializer.DeserializeObject(@"{ ""foo"": 1, ""bar"": [10, ""apples""] }");
var data = jsonObject as Dictionary<string, object>;
var array = data["bar"] as object[];
Console.WriteLine(array[1]);
}
}

[edit] Caché ObjectScript

 
Class Sample.JSON [ Abstract ]
{
 
ClassMethod GetPerson(ByRef pParms, Output pObject As %RegisteredObject) As %Status
{
Set pObject=##class(Sample.Person).%OpenId(pParms("oid"))
Quit $$$OK
}
 
}
 
Examples:
SAMPLES>Set pParms("oid")=5                                                                                       
SAMPLES>Do ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONFromObject("", "Sample.JSON", "GetPerson", .pParms)

{
"_class":"Sample.Person",
"_id":5,
"Age":80,
"DOB":33603,
"FavoriteColors":["White","Purple"],
"Home":
   {
"_class":"Sample.Address",
   "City":"Denver",
   "State":"SC",
   "Street":"6932 Second Court",
   "Zip":51309
   },
"Name":"Tillem,Will D.",
"Office":
   {
"_class":"Sample.Address",
   "City":"Queensbury",
   "State":"NV",
   "Street":"1169 Main Drive",
   "Zip":25310
   },
"SSN":"729-56-4619",
"Spouse":null
}

SAMPLES>Read json
{"_class":"Sample.Person","_id":5,"Age":80,"DOB":33603,"FavoriteColors":["White"
,"Purple"],"Home":{"_class":"Sample.Address","City":"Denver","State":"S C","Stre
et":"6932 Second Court","Zip":51309},"Name":"Tillem,Will D.","O ffice":{"_class"
:"Sample.Address","City":"Queensbury","State":"NV"," Street":"1169 Main Drive","
Zip":25310},"SSN":"729-56-4619","Spouse":null}

SAMPLES>Do ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(json, "", .person)

SAMPLES>Write person.Name
Tillem,Will D.
SAMPLES>Write person.FavoriteColors.Count()
2
SAMPLES>Write person.Home.Street
6932 Second Court

[edit] CoffeeScript

 
sample =
blue: [1, 2]
ocean: 'water'
 
json_string = JSON.stringify sample
json_obj = JSON.parse json_string
 
console.log json_string
console.log json_obj
 

[edit] Common Lisp

Library: cl-json

 
(ql:quickload '("cl-json"))
 
(json:encode-json
'#( ((foo . (1 2 3)) (bar . t) (baz . #\!))
"quux" 4/17 4.25))
 
(print (with-input-from-string
(s "{\"foo\": [1, 2, 3], \"bar\": true, \"baz\": \"!\"}")
(json:decode-json s)))
 
 
To load "cl-json":
  Load 1 ASDF system:
    cl-json
; Loading "cl-json"

[{"foo":[1,2,3],"bar":true,"baz":"!"},"quux",0.23529412,4.25]
((:FOO 1 2 3) (:BAR . T) (:BAZ . "!")) 

[edit] Clojure

Library: data.json

(use 'clojure.data.json)
 
; Load as Clojure data structures and bind the resulting structure to 'json-map'.
(def json-map (read-json "{ \"foo\": 1, \"bar\": [10, \"apples\"] }"))
 
; Use pr-str to print out the Clojure representation of the JSON created by read-json.
(pr-str json-map)
 
; Pretty-print the Clojure representation of JSON. We've come full circle.
(pprint-json json-map)

[edit] D

import std.stdio, std.json;
 
void main() {
auto j = parseJSON(`{ "foo": 1, "bar": [10, "apples"] }`);
writeln(toJSON(&j));
}
{"foo":1,"bar":[10,"apples"]}

[edit] EGL

Works with: EDT

Structures used both to construct and to parse JSON strings:

record familyMember
person person;
relationships relationship[]?;
end
 
record person
firstName string;
lastName string;
age int;
end
 
record relationship
relationshipType string;
id int;
end

Construct JSON string:

people Person[]; // Array of people
 
people.appendElement(new Person { firstName = "Frederick", lastName = "Flintstone", age = 35} );
people.appendElement(new Person { firstName = "Wilma", lastName = "Flintstone", age = 34} );
people.appendElement(new Person { firstName = "Pebbles", lastName = "Flintstone", age = 2} );
people.appendElement(new Person { firstName = "Bernard", lastName = "Rubble", age = 32} );
people.appendElement(new Person { firstName = "Elizabeth", lastName = "Rubble", age = 29} );
people.appendElement(new Person { firstName = "Bam Bam", lastName = "Rubble", age = 2} );
 
family Dictionary; // A dictionary of family members using a uid as key
family["1"] = new FamilyMember{ person = people[1], relationships = [new Relationship{ relationshipType="spouse", id = 2 }, new Relationship{ relationshipType="child", id = 3}] };
family["2"] = new FamilyMember{ person = people[2], relationships = [new Relationship{ relationshipType="spouse", id = 1 }, new Relationship{ relationshipType="child", id = 3}] };
family["3"] = new FamilyMember{ person = people[3], relationships = [new Relationship{ relationshipType="mother", id = 2 }, new Relationship{ relationshipType="father", id = 1}] };
family["4"] = new FamilyMember{ person = people[4], relationships = [new Relationship{ relationshipType="spouse", id = 5 }, new Relationship{ relationshipType="child", id = 6}] };
family["5"] = new FamilyMember{ person = people[5], relationships = [new Relationship{ relationshipType="spouse", id = 4 }, new Relationship{ relationshipType="child", id = 6}] };
family["6"] = new FamilyMember{ person = people[6], relationships = [new Relationship{ relationshipType="mother", id = 5 }, new Relationship{ relationshipType="father", id = 4}] };
 
// Convert dictionary of family members to JSON string
jsonString string = jsonLib.convertToJSON(family);
 
// Show JSON string
SysLib.writeStdout(jsonString);

Raw Output:

{
"1":{"person":{"firstName":"Frederick","lastName":"Flintstone","age":35},"relationships":[{"relationshipType":"spouse","id":2},{"relationshipType":"child","id":3}]},
"2":{"person":{"firstName":"Wilma","lastName":"Flintstone","age":34},"relationships":[{"relationshipType":"spouse","id":1},{"relationshipType":"child","id":3}]},
"3":{"person":{"firstName":"Pebbles","lastName":"Flintstone","age":2},"relationships":[{"relationshipType":"mother","id":2},{"relationshipType":"father","id":1}]},
"4":{"person":{"firstName":"Bernard","lastName":"Rubble","age":32},"relationships":[{"relationshipType":"spouse","id":5},{"relationshipType":"child","id":6}]},
"5":{"person":{"firstName":"Elizabeth","lastName":"Rubble","age":29},"relationships":[{"relationshipType":"spouse","id":4},{"relationshipType":"child","id":6}]},
"6":{"person":{"firstName":"Bam Bam","lastName":"Rubble","age":2},"relationships":[{"relationshipType":"mother","id":5},{"relationshipType":"father","id":4}]}
}

Validated Output (partial):

{
    "1": {
        "person": {
            "firstName": "Frederick",
            "lastName": "Flintstone",
            "age": 35
        },
        "relationships": [
            {
                "relationshipType": "spouse",
                "id": 2
            },
            {
                "relationshipType": "child",
                "id": 3
            }
        ]
    },
...
}

Parse JSON:

// Convert JSON string into dictionary of family members
family Dictionary;
jsonLib.convertFromJSON(jsonString, family);
 
// List family members and their relationships
familyMember FamilyMember;
relation FamilyMember;
 
keys string[] = family.getKeys();
for(i int from 1 to keys.getSize())
 
SysLib.writeStdout("----------------------------------------------------");
 
familyMember = family[keys[i]];
 
SysLib.writeStdout(familyMember.person.lastName + ", " + familyMember.person.firstName + " - " + familyMember.person.age);
 
for(j int from 1 to familyMember.relationships.getSize())
id string = familyMember.relationships[j].id;
relation = family[id];
SysLib.writeStdout(familyMember.relationships[j].relationshipType + ": " +
relation.person.lastName + ", " + relation.person.firstName);
end
 
end

Output:

Flintstone, Frederick - 35
spouse: Flintstone, Wilma
child: Flintstone, Pebbles
----------------------------------------------------
Flintstone, Wilma - 34
spouse: Flintstone, Frederick
child: Flintstone, Pebbles
----------------------------------------------------
Flintstone, Pebbles - 2
mother: Flintstone, Wilma
father: Flintstone, Frederick
----------------------------------------------------
Rubble, Bernard - 32
spouse: Rubble, Elizabeth
child: Rubble, Bam Bam
----------------------------------------------------
Rubble, Elizabeth - 29
spouse: Rubble, Bernard
child: Rubble, Bam Bam
----------------------------------------------------
Rubble, Bam Bam - 2
mother: Rubble, Elizabeth
father: Rubble, Bernard

The examples above illustrate that it is possible to perform manual conversions to and from a JSON format but in EGL it is much more common for the programming language to handle these conversion automatically as a natural part of service invocations. Below is an example of a function definition designed to consume the Google Maps Geocoding service. The results are returned in a JSON format and parsed by EGL into records that mirror the structure of the reply.

// Service function definition
function geocode(address String) returns (GoogleGeocoding) {
@Resource{uri = "binding:GoogleGeocodingBinding"},
@Rest{method = _GET, uriTemplate = "/json?address={address}&sensor=false",
requestFormat = None, responseFormat = JSON}
}
 
// Invoke service function
call geocode("111 Maple Street, Somewhere, CO") returning to callback;
 
function callBack(result GoogleGeocoding in)
SysLib.writeStdout(result.status);
SysLib.writeStdout(result.results[1].geometry.location.lat);
SysLib.writeStdout(result.results[1].geometry.location.lng);
end

[edit] Erlang

Use the JSON library for Erlang (mochijson) from mochiweb. The JSON code is extracted from wikipedia

 
-module(json).
-export([main/0]).
 
main() ->
JSON =
"{
\"firstName\": \"John\",
\"lastName\": \"Smith\",
\"age\": 25,
\"address\": {
\"streetAddress\": \"21 2nd Street\",
\"city\": \"New York\",
\"state\": \"NY\",
\"postalCode\": \"10021\"
},
\"phoneNumber\": [
{
\"type\": \"home\",
\"number\": \"212 555-1234\"
},
{
\"type\": \"fax\",
\"number\": \"646 555-4567\"
}
]
}"
,
Erlang =
{struct,
[{"firstName","John"},
{"lastName","Smith"},
{"age",25},
{"address",
{struct,[{"streetAddress","21 2nd Street"},
{"city","New York"},
{"state","NY"},
{"postalCode","10021"}]}},
{"phoneNumber",
{array,[{struct,[{"type","home"},{"number","212 555-1234"}]},
{struct,[{"type","fax"},{"number","646 555-4567"}]}]}}]},
io:format("JSON -> Erlang\n~p\n",[mochijson:decode(JSON)]),
io:format("Erlang -> JSON\n~s\n",[mochijson:encode(Erlang)]).
 

Output:

JSON -> Erlang
{struct,[{"firstName","John"},
         {"lastName","Smith"},
         {"age",25},
         {"address",
          {struct,[{"streetAddress","21 2nd Street"},
                   {"city","New York"},
                   {"state","NY"},
                   {"postalCode","10021"}]}},
         {"phoneNumber",
          {array,[{struct,[{"type","home"},{"number","212 555-1234"}]},
                  {struct,[{"type","fax"},{"number","646 555-4567"}]}]}}]}
Erlang -> JSON
{"firstName":"John","lastName":"Smith","age":25,"address":{"streetAddress":"21 2nd Street","city":"New York","state":"NY","postalCode":"10021"},"phoneNumber":[{"type":"home","number":"212 555-1234"},{"type":"fax","number":"646 555-4567"}]}

[edit] Factor

 
USING: json.writer json.reader ;
 
SYMBOL: foo
 
! Load a JSON string into a data structure
"[[\"foo\",1],[\"bar\",[10,\"apples\"]]]" json> foo set
 
 
! Create a new data structure and serialize into JSON
{ { "blue" { "ocean" "water" } } >json
 

[edit] Fantom

 
using util
 
class Json
{
public static Void main ()
{
Str input := """{"blue": [1, 2], "ocean": "water"}"""
Map jsonObj := JsonInStream(input.in).readJson
 
echo ("Value for 'blue' is: " + jsonObj["blue"])
jsonObj["ocean"] = ["water":["cold", "blue"]]
Map ocean := jsonObj["ocean"]
echo ("Value for 'ocean/water' is: " + ocean["water"])
output := JsonOutStream(Env.cur.out)
output.writeJson(jsonObj)
echo ()
}
}
 

Output:

Value for 'blue' is: [1, 2]
Value for 'ocean/water' is: [cold, blue]
{"blue":[1,2],
"ocean":{"water":["cold","blue"]}}

[edit] FunL

Since FunL map syntax is conforms to JSON, the built-in function eval() can be used to parse a JSON string. Built-in println() also produces JSON conformant output. This method only uses built-in functions but is comparatively slow.

println( eval('{ "foo": 1, "bar": [10, "apples"] }') )

Using module json gives better performance and also pretty prints the JSON output.

import json.*
 
DefaultJSONWriter.write( JSONReader({'ints', 'bigInts'}).fromString('{ "foo": 1, "bar": [10, "apples"] }') )
Output:
{"foo": 1, "bar": [10, "apples"]}
{
  "foo": 1,
  "bar": [
    10,
    "apples"
  ]
}

[edit] Go

Example below shows simple correspondence between JSON objects and Go maps, and shows that you don't have to know anything about the structure of the JSON data to read it in.

package main
 
import "encoding/json"
import "fmt"
 
func main() {
var data interface{}
err := json.Unmarshal([]byte(`{"foo":1, "bar":[10, "apples"]}`), &data)
if err == nil {
fmt.Println(data)
} else {
fmt.Println(err)
}
 
sample := map[string]interface{}{
"blue": []interface{}{1, 2},
"ocean": "water",
}
json_string, err := json.Marshal(sample)
if err == nil {
fmt.Println(string(json_string))
} else {
fmt.Println(err)
}
}
Output:
map[bar:[10 apples] foo:1]
{"blue":[1,2],"ocean":"water"}

Example below demonstrates more typical case where you have an expected correspondence between JSON data and some composite data types in your program, and shows how the correspondence doesn't have to be exact.

package main
 
import "encoding/json"
import "fmt"
 
type Person struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
Addr *Address `json:"address,omitempty"`
Ph []string `json:"phone,omitempty"`
}
 
type Address struct {
Street string `json:"street"`
City string `json:"city"`
State string `json:"state"`
Zip string `json:"zip"`
}
 
func main() {
// compare with output, note apt field ignored, missing fields
// have zero values.
jData := []byte(`{
"name": "Smith",
"address": {
"street": "21 2nd Street",
"apt": "507",
"city": "New York",
"state": "NY",
"zip": "10021"
}
}`
)
var p Person
err := json.Unmarshal(jData, &p)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("%+v\n  %+v\n\n", p, p.Addr)
}
 
// compare with output, note empty fields omitted.
pList := []Person{
{
Name: "Jones",
Age: 21,
},
{
Name: "Smith",
Addr: &Address{"21 2nd Street", "New York", "NY", "10021"},
Ph: []string{"212 555-1234", "646 555-4567"},
},
}
jData, err = json.MarshalIndent(pList, "", " ")
if err != nil {
fmt.Println(err)
} else {
fmt.Println(string(jData))
}
}
Output:
{Name:Smith Age:0 Addr:0xf840026080 Ph:[]}
  &{Street:21 2nd Street City:New York State:NY Zip:10021}

[
    {
        "name": "Jones",
        "age": 21
    },
    {
        "name": "Smith",
        "address": {
            "street": "21 2nd Street",
            "city": "New York",
            "state": "NY",
            "zip": "10021"
        },
        "phone": [
            "212 555-1234",
            "646 555-4567"
        ]
    }
]

[edit] Groovy

Solution requires Groovy 1.8 or later.

Note that JsonSlurper accepts an extra comma such as [1,2,3,]. This is an extension to the [JSON grammar].

def slurper = new groovy.json.JsonSlurper()
def result = slurper.parseText('''
{
"people":[
{"name":{"family":"Flintstone","given":"Frederick"},"age":35,"relationships":{"wife":"people[1]","child":"people[4]"}},
{"name":{"family":"Flintstone","given":"Wilma"},"age":32,"relationships":{"husband":"people[0]","child":"people[4]"}},
{"name":{"family":"Rubble","given":"Barnard"},"age":30,"relationships":{"wife":"people[3]","child":"people[5]"}},
{"name":{"family":"Rubble","given":"Elisabeth"},"age":32,"relationships":{"husband":"people[2]","child":"people[5]"}},
{"name":{"family":"Flintstone","given":"Pebbles"},"age":1,"relationships":{"mother":"people[1]","father":"people[0]"}},
{"name":{"family":"Rubble","given":"Bam-Bam"},"age":1,"relationships":{"mother":"people[3]","father":"people[2]"}},
]
}
'''
)

Test:

result.each { println it.key; it.value.each {person -> println person} }
 
assert result.people[0].name == [family:'Flintstone', given:'Frederick']
assert result.people[4].age == 1
assert result.people[2].relationships.wife == 'people[3]'
assert result.people[3].name == [family:'Rubble', given:'Elisabeth']
assert Eval.x(result, 'x.' + result.people[2].relationships.wife + '.name') == [family:'Rubble', given:'Elisabeth']
assert Eval.x(result, 'x.' + result.people[1].relationships.husband + '.name') == [family:'Flintstone', given:'Frederick']

Output:

people
[age:35, name:[given:Frederick, family:Flintstone], relationships:[child:people[4], wife:people[1]]]
[age:32, name:[given:Wilma, family:Flintstone], relationships:[child:people[4], husband:people[0]]]
[age:30, name:[given:Barnard, family:Rubble], relationships:[child:people[5], wife:people[3]]]
[age:32, name:[given:Elisabeth, family:Rubble], relationships:[child:people[5], husband:people[2]]]
[age:1, name:[given:Pebbles, family:Flintstone], relationships:[mother:people[1], father:people[0]]]
[age:1, name:[given:Bam-Bam, family:Rubble], relationships:[mother:people[3], father:people[2]]]

[edit] Harbour

Parse JSON string into the arr variable:

LOCAL arr
hb_jsonDecode( '[101,[26,"Test1"],18,false]', @arr )

Output the JSON representation of an array arr:

LOCAL arr := { 101, { 18, "Test1" }, 18, .F. }
? hb_jsonEncode( arr )
// The output is:
// [101,[26,"Test1"],18,false]

[edit] Haskell

Uses the Aeson library from hackage (http://hackage.haskell.org/package/aeson).

 
{-# LANGUAGE OverloadedStrings #-}
 
import Data.Aeson
import Data.Attoparsec (parseOnly)
import Data.Text
import qualified Data.ByteString.Lazy.Char8 as B
import qualified Data.ByteString.Char8 as S
 
testdoc = object [
"foo" .= (1 :: Int),
"bar" .= ([1.3, 1.6, 1.9] :: [Double]),
"baz" .= ("some string" :: Text),
"other" .= object [
"yes" .= ("sir" :: Text)
]
]
 
main = do
let out = encode testdoc
B.putStrLn out
case parseOnly json (S.concat $ B.toChunks out) of
Left e -> error $ "strange error re-parsing json: " ++ (show e)
Right v | v /= testdoc -> error "documents not equal!"
Right v | otherwise -> print v
 
 

[edit] J

Here is a minimal implementation based on an old email message.

NB.               character classes:
NB. 0: whitespace
NB. 1: "
NB. 2: \
NB. 3: [ ] , { } :
NB. 4: ordinary
classes=.3<. '"\[],{}:' (#@[ |&>: i.) a.
classes=.0 (I.a.e.' ',CRLF,TAB)} (]+4*0=])classes
 
words=:(0;(0 10#:10*".;._2]0 :0);classes)&;: NB. states:
0.0 1.1 2.1 3.1 4.1 NB. 0 whitespace
1.0 5.0 6.0 1.0 1.0 NB. 1 "
4.0 4.0 4.0 4.0 4.0 NB. 2 \
0.3 1.2 2.2 3.2 4.2 NB. 3 { : , } [ ]
0.3 1.2 2.0 3.2 4.0 NB. 4 ordinary
0.3 1.2 2.2 3.2 4.2 NB. 5 ""
1.0 1.0 1.0 1.0 1.0 NB. 6 "\
)
 
tokens=. ;:'[ ] , { } :'
actions=: lBra`rBracket`comma`lBra`rBracket`colon`value
 
NB. action verbs argument conventions:
NB. x -- boxed json word
NB. y -- boxed json state stack
NB. result -- new boxed json state stack
NB.
NB. json state stack is an list of boxes of incomplete lists
NB. (a single box for complete, syntactically valid json)
jsonParse=: 0 {:: (,a:) ,&.> [: actions@.(tokens&i.@[)/ [:|.a:,words
 
lBra=: a: ,~ ]
rBracket=: _2&}.@], [:< _2&{::@], _1&{@]
comma=: ]
rBrace=: _2&}.@], [:< _2&{::@], [:|: (2,~ [: -:@$ _1&{@]) $ _1&{@]
colon=: ]
value=: _1&}.@], [:< _1&{::@], jsonValue&.>@[
 
NB. hypothetically, jsonValue should strip double quotes
NB. interpret back slashes
NB. and recognize numbers
jsonValue=:]
 
 
require'strings'
jsonSer1=: ']' ,~ '[' }:@;@; (',' ,~ jsonSerialize)&.>
jsonSer0=: '"', jsonEsc@:":, '"'"_
jsonEsc=: rplc&(<;._1' \ \\ " \"')
jsonSerialize=:jsonSer0`jsonSer1@.(*@L.)

Example use:

   jsonParse'{ "blue": [1,2], "ocean": "water" }'
┌──────────────────────────────┐
│┌──────┬─────┬───────┬───────┐│
││"blue"│┌─┬─┐│"ocean"│"water"││
││ ││1│2││ │ ││
││ │└─┴─┘│ │ ││
│└──────┴─────┴───────┴───────┘│
└──────────────────────────────┘
jsonSerialize jsonParse'{ "blue": [1,2], "ocean": "water" }'
[["\"blue\"",["1","2"],"\"ocean\"","\"water\""]]

Note that these are not strict inverses of each other. These routines allow data to be extracted from json and packed into json format, but only in a minimalistic sense. No attempts are made to preserve the subtleties of type and structure which json can carry. This should be good enough for most applications which are required to deal with json but will not be adequate for ill behaved applications which exploit the typing mechanism to carry significant information.

Also, a different serializer will probably be necessary, if you are delivering json to legacy javascript. Nevertheless, these simplifications are probably appropriate for practical cases.

[edit] Java

This uses Gson, a library to convert JSON to Java objects and vice-versa.

import com.google.gson.Gson;
 
public class JsonExample {
 
public static void main(String[] args) {
Gson gson = new Gson();
String json = "{ \"foo\": 1, \"bar\": [ \"10\", \"apples\"] }";
 
MyJsonObject obj = gson.fromJson(json, MyJsonObject.class);
 
System.out.println(obj.getFoo());
 
for(String bar : obj.getBar()) {
System.out.println(bar);
}
 
obj = new MyJsonObject(2, new String[] { "20", "oranges" });
json = gson.toJson(obj);
 
System.out.println(json);
}
 
}
 
class MyJsonObject {
 
private int foo;
private String[] bar;
 
public MyJsonObject(int foo, String[] bar) {
this.foo = foo;
this.bar = bar;
}
 
public int getFoo() {
return foo;
}
 
public String[] getBar() {
return bar;
}
 
}

[edit] JavaScript

Requires JSON library, now present in some browsers.

var data = JSON.parse('{ "foo": 1, "bar": [10, "apples"] }');
 
var sample = { "blue": [1,2], "ocean": "water" };
var json_string = JSON.stringify(sample);

Of course, it IS called JavaScript Object Notation, so it is a JavaScript object literal, and you can, alternately, parse it by just eval'ing it. This should work in any browser without a library. (Eval may be dangerous, depending on the source of the data.) However, there is an ambiguity with parsing JavaScript object literals by themselves, where it might be mistakenly interpreted as a block, and the key followed by a colon as a label. To avoid this, remember to surround it in parentheses to force it to be interpreted as an expression:

var data = eval('(' + '{ "foo": 1, "bar": [10, "apples"] }' + ')');

[edit] jq

JSON is jq's native data format, so nothing need be done to parse JSON input. For example, to "pretty print" a stream of JSON entities (including scalars), it would be sufficient to use the jq program:
 . 

Here are the jq equivalents of the examples given in the section on Julia, assuming the file data.json holds the following JSON text:

{ "blue": [1,2], "ocean": "water" }

jq -c . data.json

produces:

{"blue":[1,2],"ocean":"water"}

jq tostring data.json

produces: "{\"blue\":[1,2],\"ocean\":\"water\"}"

[edit] Julia

The JSON module is installed by running Pkg.add("JSON").

 
julia> import JSON
 
julia> JSON.parse("""{ "blue": [1,2], "ocean": "water" }""")
["ocean"=>"water","blue"=>{1,2}]
 
julia> JSON.json({"blue" => [1,2] , "ocean" => "water"})
"{\"ocean\":\"water\",\"blue\":[1,2]}"

[edit] Lasso

// Javascript objects are represented by maps in Lasso
local(mymap = map(
'success' = true,
'numeric' = 11,
'string' = 'Eleven'
))
 
json_serialize(#mymap) // {"numeric": 11,"string": "Eleven","success": true}
'<br />'
 
// Javascript arrays are represented by arrays
local(opendays = array(
'Monday',
'Tuesday'
))
 
local(closeddays = array(
'Wednesday',
'Thursday',
'Friday'
))
 
json_serialize(#opendays) // ["Monday", "Tuesday"]
'<br />'
json_serialize(#closeddays) // ["Wednesday", "Thursday", "Friday"]
'<br />'
 
#mymap -> insert('Open' = #opendays)
#mymap -> insert('Closed' = #closeddays)
 
local(myjson = json_serialize(#mymap))
#myjson // {"Closed": ["Wednesday", "Thursday", "Friday"],"numeric": 11,"Open": ["Monday", "Tuesday"],"string": "Eleven","success": true}
'<br />'
 
json_deserialize(#myjson) // map(Closed = array(Wednesday, Thursday, Friday), numeric = 11, Open = array(Monday, Tuesday), string = Eleven, success = true)

[edit] LFE

This example uses the third-party library "Jiffy".

[edit] Encoding

 
(: jiffy encode (list 1 2 3 '"apple" 'true 3.14))
 

The result from that can be made a little more legible with the following:

 
(: erlang binary_to_list
(: jiffy encode (list 1 2 3 '"apple" 'true 3.14)))
 

[edit] Decoding

We can run the encoding example in reverse, and get back what we put in above with the following:

 
(: jiffy decode '"[1,2,3,[97,112,112,108,101],true,3.14]")
 

Here's a key-value example:

 
(: jiffy decode '"{\"foo\": [1, 2, 3]}")
 

[edit] Decoding to Patterns

We can also extract the key and value using Erlang patterns:

 
(let (((tuple (list (tuple key value)))
(: jiffy decode '"{\"foo\": [1, 2, 3]}")))
(: io format '"~p: ~p~n" (list key value)))
 

[edit] Lua

Using the luajson library:

local json = require("json")
 
local json_data = [=[[
42,
3.14159,
[ 2, 4, 8, 16, 32, 64, "apples", "bananas", "cherries" ],
{ "H": 1, "He": 2, "X": null, "Li": 3 },
null,
true,
false
]]=]
 
print("Original JSON: " .. json_data)
local data = json.decode(json_data)
json.util.printValue(data, 'Lua')
print("JSON re-encoded: " .. json.encode(data))
 
local data = {
42,
3.14159,
{
2, 4, 8, 16, 32, 64,
"apples",
"bananas",
"cherries"
},
{
H = 1,
He = 2,
X = json.util.null(),
Li = 3
},
json.util.null(),
true,
false
}
 
print("JSON from new Lua data: " .. json.encode(data))

Since in Lua nil signifies an undefined value, i.e. a variable or table entry with a nil value is undistinguishable from an undefined variable or non-existing table entry, a null value in JSON notation is decoded to a special function value, which ensures that it can be re-encoded properly to null again. To manually insert a null value in the JSON output, use the json.util.null function.

Output:

   Original JSON: [
       42,
       3.14159,
       [ 2, 4, 8, 16, 32, 64, "apples", "bananas", "cherries" ],
       { "H": 1, "He": 2, "X": null, "Li": 3 },
       null,
       true,
       false
   ]
   Lua= {
    1=42
    2=3.14159
    3= {
     1=2
     2=4
     3=8
     4=16
     5=32
     6=64
     7=apples
     8=bananas
     9=cherries
    4= {
     Li=3
     He=2
     H=1
     X=function: 0x8f6f00
    5=function: 0x8f6f00
    6=true
    7=false
   JSON re-encoded: [42,3.14159,[2,4,8,16,32,64,"apples","bananas","cherries"],{"Li":3,"He":2,"H":1,"X":null},null,true,false]
   JSON from new Lua data: [42,3.14159,[2,4,8,16,32,64,"apples","bananas","cherries"],{"Li":3,"He":2,"H":1,"X":null},null,true,false]

[edit] Mathematica

 
data = ImportString["{ \"foo\": 1, \"bar\": [10, \"apples\"] }","JSON"]
ExportString[data, "JSON"]
 

[edit] MATLAB / Octave

The toolbox JSONlab is doing a nice job to read (loadjson.m) and write (savejson.m) data in JSON format.

[edit] NetRexx

[edit] json.org Library

This uses a library provided by json.org to serialize/deserialize JSON objects.

/* NetRexx */
options replace format comments java crossref symbols nobinary
 
import java.util.List
import org.json.JSONObject
import org.json.JSONArray
import org.json.JSONTokener
import org.json.JSONException
 
/**
* Using library from json.org
*
* @see http://www.json.org/java/index.html
*/

class RJson01 public
 
properties private constant
JSON_DWARFS = '' -
'{\n' -
' "F1937_1" : {\n' -
' "title"  : "Snow White and the Seven Dwarfs",\n' -
' "year"  : 1937,\n' -
' "medium" : "film",\n' -
' "dwarfs" : [ "Grumpy", "Happy", "Sleepy", "Bashful", "Sneezy", "Dopey", "Doc" ]\n' -
' },\n' -
' "F2012_1" : {\n' -
' "title"  : "Mirror, Mirror",\n' -
' "year"  : 2012,\n' -
' "medium" : "film",\n' -
' "dwarfs" : [ "Grimm", "Butcher", "Wolf", "Napoleon", "Half Pint", "Grub", "Chuckles" ]\n' -
' },\n' -
'}'
 
/**
* A bean that looks like the following JSON
* <pre>
* {
* "F2012_2" : {
* "title"  : "Snow White & the Huntsman",
* "year"  : 2012,
* "medium" : "film",
* "dwarfs" : [ "Beith", "Quert", "Muir", "Coll", "Duir", "Gus", "Gort", "Nion" ]
* }
* }
* </pre>
*/

SAMPLE_BEAN = DwarfBean( -
"F2012_2", -
"Snow White & the Huntsman", -
Long(2012), -
"film", -
Arrays.asList([String "Beith", "Quert", "Muir", "Coll", "Duir", "Gus", "Gort", "Nion"]) -
)
 
method main(args = String[]) public static
say json2bean(JSON_DWARFS)
say
say bean2json(SAMPLE_BEAN)
say
return
 
method json2bean(dwarfs) public static returns List
say "Make beans from this JSON string:"
say dwarfs
jsonBeans = ArrayList()
do
jd = JSONObject(JSONTokener(dwarfs))
ns = JSONObject.getNames(jd)
name = String
loop name over ns
dwarves = ArrayList()
jn = jd.getJSONObject(name)
title = jn.getString('title')
year = Long(jn.getLong('year'))
medium = jn.getString('medium')
dwa = jn.getJSONArray('dwarfs')
loop di = 0 to dwa.length() - 1
dwarves.add(dwa.getString(di))
end di
jb = DwarfBean(name, title, year, medium, dwarves)
jsonBeans.add(jb.toString())
end name
catch ex = JSONException
ex.printStackTrace()
end
return jsonBeans
 
method bean2json(sb = DwarfBean) public static returns String
say "Make JSONObject from this bean:"
say sb
jsonString = String
do
jd = JSONObject(sb)
jo = JSONObject()
jo = jo.put(sb.keyGet(), jd)
jsonString = jo.toString(2)
catch ex = JSONException
ex.printStackTrace()
end
return jsonString
 
-- =============================================================================
class RJson01.DwarfBean public binary
properties private
key = String -- not part of bean
properties indirect
title = String
year = Long
medium = String
dwarfs = List
 
method DwarfBean(key_ = String null, title_ = String null, year_ = Long null, medium_ = String null, dwarfs_ = List null) public
keyPut(key_)
setTitle(title_)
setYear(year_)
setMedium(medium_)
setDwarfs(dwarfs_)
return
 
method keyPut(key_ = String) public
key = key_
return
 
method keyGet() returns String
return key
 
method toString public returns String
ts = StringBuilder()
ts.append(String.format("%s@%08x ", [Object this.getClass().getSimpleName(), Integer(hashCode())]))
ts.append('[')
ts.append('key='String.valueOf(keyGet())', ')
ts.append('title='String.valueOf(getTitle())', ')
ts.append('year='String.valueOf(getYear())', ')
ts.append('medium='String.valueOf(getMedium())', ')
ts.append('dwarfs='String.valueOf(getDwarfs()))
ts.append(']')
return ts.toString()
 

Output:

Make beans from this JSON string:
 {
   "F1937_1" : {
     "title"  : "Snow White and the Seven Dwarfs",
     "year"   : 1937,
     "medium" : "film",
     "dwarfs" : [ "Grumpy", "Happy", "Sleepy", "Bashful", "Sneezy", "Dopey", "Doc" ]
   },
   "F2012_1" : {
     "title"  : "Mirror, Mirror",
     "year"   : 2012,
     "medium" : "film",
     "dwarfs" : [ "Grimm", "Butcher", "Wolf", "Napoleon", "Half Pint", "Grub", "Chuckles" ]
   },
 }
[DwarfBean@07377711 [key=F2012_1, title=Mirror, Mirror, year=2012, medium=film, dwarfs=[Grimm, Butcher, Wolf, Napoleon, Half Pint, Grub, Chuckles]], DwarfBean@19f16e6e [key=F1937_1, title=Snow White and the Seven Dwarfs, year=1937, medium=film, dwarfs=[Grumpy, Happy, Sleepy, Bashful, Sneezy, Dopey, Doc]]]

Make JSONObject from this bean:
DwarfBean@39890510 [key=F2012_2, title=Snow White & the Huntsman, year=2012, medium=film, dwarfs=[Beith, Quert, Muir, Coll, Duir, Gus, Gort, Nion]]
{"F2012_2": {
  "title": "Snow White & the Huntsman",
  "dwarfs": [
    "Beith",
    "Quert",
    "Muir",
    "Coll",
    "Duir",
    "Gus",
    "Gort",
    "Nion"
  ],
  "year": 2012,
  "medium": "film"
}}

[edit] Google gson Library

This uses Gson, a library to convert JSON to Java objects and vice-versa.

/* NetRexx */
options replace format comments java crossref symbols nobinary
 
import com.google.gson.
import java.util.List
 
/**
* Using google-gson library
*
* @see https://code.google.com/p/google-gson/
*/

class RJson02 public
 
properties private constant
JSON_DWARFS = '' -
'{\n' -
' "title" : "Snow White and the Seven Dwarfs",\n' -
' "year"  : 1937,\n' -
' "medium": "film",\n' -
' "dwarfs": [ "Grumpy", "Happy", "Sleepy", "Bashful", "Sneezy", "Dopey", "Doc" ]\n' -
'}'
 
/**
* A bean that looks like the following JSON
* <pre>
* {
* "title"  : "Snow White & the Huntsman",
* "year"  : 2012,
* "medium" : "film",
* "dwarfs" : [ "Beith", "Quert", "Muir", "Coll", "Duir", "Gus", "Gort", "Nion" ]
* }
* </pre>
*/

SAMPLE_BEAN = RJSON02.DwarfBean( -
/*"F2012_2",*/ -
"Snow White and the Huntsman", -
Long(2012), -
"film", -
Arrays.asList([String "Beith", "Quert", "Muir", "Coll", "Duir", "Gus", "Gort", "Nion"]) -
)
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method main(args = String[]) public static
gsonObj = GsonBuilder().setPrettyPrinting().create()
jsonBean = RJson02.DwarfBean gsonObj.fromJson(JSON_DWARFS, RJson02.DwarfBean.class)
say JSON_DWARFS
say jsonBean.toString()
say
 
json = gsonObj.toJson(SAMPLE_BEAN);
say json
say SAMPLE_BEAN.toString()
say
 
return
 
-- =============================================================================
class RJson02.DwarfBean public binary
properties indirect
title = String
year = Long
medium = String
dwarfs = List
 
method DwarfBean(title_ = String null, year_ = Long null, medium_ = String null, dwarfs_ = List null) public
setTitle(title_)
setYear(year_)
setMedium(medium_)
setDwarfs(dwarfs_)
return
 
method toString public returns String
ts = StringBuilder()
ts.append(String.format("%s@%08x ", [Object this.getClass().getSimpleName(), Integer(hashCode())]))
ts.append('[')
ts.append('title='String.valueOf(getTitle())', ')
ts.append('year='String.valueOf(getYear())', ')
ts.append('medium='String.valueOf(getMedium())', ')
ts.append('dwarfs='String.valueOf(getDwarfs()))
ts.append(']')
return ts.toString()
 

Output:

 {
   "title" : "Snow White and the Seven Dwarfs",
   "year"  : 1937,
   "medium": "film",
   "dwarfs": [ "Grumpy", "Happy", "Sleepy", "Bashful", "Sneezy", "Dopey", "Doc" ]
 }
DwarfBean@63f5e4b6 [title=Snow White and the Seven Dwarfs, year=1937, medium=film, dwarfs=[Grumpy, Happy, Sleepy, Bashful, Sneezy, Dopey, Doc]]

{
  "title": "Snow White and the Huntsman",
  "year": 2012,
  "medium": "film",
  "dwarfs": [
    "Beith",
    "Quert",
    "Muir",
    "Coll",
    "Duir",
    "Gus",
    "Gort",
    "Nion"
  ]
}
DwarfBean@6d63de20 [title=Snow White and the Huntsman, year=2012, medium=film, dwarfs=[Beith, Quert, Muir, Coll, Duir, Gus, Gort, Nion]]

[edit] Nimrod

import json
 
var data = parseJson("""{ "foo": 1, "bar": [10, "apples"] }""")
echo data["foo"]
echo data["bar"]
 
var js = %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
echo js

Output:

1
[ 10,  "apples"]
[ { "name": "John",  "age": 30 },  { "name": "Susan",  "age": 31 }]

[edit] Objective-C

Works with: 10.7+ version Xcode 4.4+
NSString *jsonString = @"{ \"foo\": 1, \"bar\": [10, \"apples\"] }";
id obj = [NSJSONSerialization
JSONObjectWithData: [jsonString dataUsingEncoding: NSUTF8StringEncoding]
options: 0
error: NULL];
NSLog(@"%@", obj);
 
NSDictionary *dict = @{ @"blue": @[@1, @2], @"ocean": @"water"};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject: dict
options: 0
error: NULL];
NSString *jsonString2 = [[NSString alloc] initWithData: jsonData
encoding: NSUTF8StringEncoding];
NSLog(@"%@", jsonString2);
 

[edit] Objeck

 
use Struct;
use JSON;
 
bundle Default {
class Json {
function : Main(args : String[]) ~ Nil {
parser := JSONParser->New("{ \"foo\": 1, \"bar\": [10, \"apples\"] }");
root := parser->Parse();
if(root <> Nil) {
root->ToString()->PrintLine();
};
}
}
}

[edit] OCaml

[edit] Using json-wheel/json-static libs

Library: json-wheel
Library: json-static
type json item =
< name "Name": string;
kingdom "Kingdom": string;
phylum "Phylum": string;
class_ "Class": string;
order "Order": string;
family "Family": string;
tribe "Tribe": string
>
 
let str = "
{
\"
Name\": \"camel\",
\"
Kingdom\": \"Animalia\",
\"
Phylum\": \"Chordata\",
\"
Class\": \"Mammalia\",
\"
Order\": \"Artiodactyla\",
\"
Family\": \"Camelidae\",
\"
Tribe\": \"Camelini\"
}"

 
let () =
let j = Json_io.json_of_string str in
print_endline (Json_io.string_of_json j);

compile with:

ocamlfind opt -o j.opt j.ml -linkpkg -package json-static -syntax camlp4o

[edit] Using yojson lib

Library: yojson
open Yojson.Basic.Util
 
let s = "
{ \"
name\": \"John Doe\",
\"
pages\": [
{ \"
id\": 1,
\"
title\": \"The Art of Flipping Coins\",
\"
url\": \"http://example.com/398eb027/1\"
},
{ \"
id\": 2, \"deleted\": true },
{ \"
id\": 3,
\"
title\": \"Artichoke Salad\",
\"
url\": \"http://example.com/398eb027/3\"
},
{ \"
id\": 4,
\"
title\": \"Flying Bananas\",
\"
url\": \"http://example.com/398eb027/4\"
}
]
}"

 
let extract_titles json =
[json]
|> filter_member "pages"
|> flatten
|> filter_member "title"
|> filter_string
 
let () =
let json = Yojson.Basic.from_string s in
List.iter print_endline (extract_titles json)

Compile and run:

$ ocamlfind ocamlopt -o filtering filtering.ml -package yojson -linkpkg
$ ./filtering
The Art of Flipping Coins
Artichoke Salad
Flying Bananas

[edit] OpenEdge/Progress

The WRITE-JSON and READ-JSON methods were introduced in Progress OpenEdge 10.2B.

/* using a longchar to read and write to, can also be file, memptr, stream */
DEFINE VARIABLE lcjson AS LONGCHAR NO-UNDO.
 
/* temp-table defines object, can also be dataset */
DEFINE TEMP-TABLE example
FIELD blue AS INTEGER EXTENT 2
FIELD ocean AS CHARACTER
.
CREATE example.
ASSIGN
example.blue [1] = 1
example.blue [2] = 2
example.ocean = "water"
.
/* write-json to put result in lcjson, true indicates formatted */
TEMP-TABLE example:DEFAULT-BUFFER-HANDLE:WRITE-JSON( "LONGCHAR", lcjson, TRUE ).
 
/* display result */
MESSAGE
STRING( lcjson )
VIEW-AS ALERT-BOX.
 
/* empty results */
EMPTY TEMP-TABLE example.
 
/* read-json to get result from lcjson */
TEMP-TABLE example:DEFAULT-BUFFER-HANDLE:READ-JSON( "LONGCHAR", lcjson ).
 
FIND example.
/* display results */
MESSAGE
example.blue [1] example.blue [2] SKIP
example.ocean
VIEW-AS ALERT-BOX.

Output write-json:

---------------------------
Message
---------------------------
{"example": [
  {
    "blue": [
      1,
      2
    ],
    "ocean": "water"
  }
]}
---------------------------
OK   
---------------------------

Output read-json:

---------------------------
Message
---------------------------
1 2 
water
---------------------------
OK   
---------------------------

[edit] Oz

With the JSON library from here:

declare
[JSON] = {Module.link ['JSON.ozf']}
 
{System.show {JSON.decode "{ \"foo\": 1, \"bar\": [10, \"apples\"] }"}}
 
Sample = object(blue:array(1 2) ocean:"water")
{System.showInfo {JSON.encode Sample}}

Output:

object(bar:array(10 [97 112 112 108 101 115]) foo:1)
{"blue":[1,2],"ocean":"water"}

[edit] Perl

Library: JSON
use JSON;
 
my $data = decode_json('{ "foo": 1, "bar": [10, "apples"] }');
 
my $sample = { blue => [1,2], ocean => "water" };
my $json_string = encode_json($sample);

[edit] Perl 6

Using JSON::Tiny

use JSON::Tiny;
 
my $data = from-json('{ "foo": 1, "bar": [10, "apples"] }');
 
my $sample = { blue => [1,2], ocean => "water" };
my $json_string = to-json($sample);

[edit] PHP

<?php
$data = json_decode('{ "foo": 1, "bar": [10, "apples"] }'); // dictionaries will be returned as objects
$data2 = json_decode('{ "foo": 1, "bar": [10, "apples"] }', true); // dictionaries will be returned as arrays
 
$sample = array( "blue" => array(1,2), "ocean" => "water" );
$json_string = json_encode($sample);
?>

[edit] PicoLisp

PicoLisp has no JSON library, but it is easy enough to write one. The following supports only fixpoint numbers (no floating point, as it doesn't exist in PicoLisp). Arrays and objects are both mapped to lists.

(de checkJson (X Item)
(unless (= X Item)
(quit "Bad JSON" Item) ) )
 
(de readJson ()
(case (read "_")
("{"
(make
(for (X (readJson) (not (= "}" X)) (readJson))
(checkJson ":" (readJson))
(link (cons X (readJson)))
(T (= "}" (setq X (readJson))))
(checkJson "," X) ) ) )
("["
(make
(link T) # Array marker
(for (X (readJson) (not (= "]" X)) (readJson))
(link X)
(T (= "]" (setq X (readJson))))
(checkJson "," X) ) ) )
(T
(let X @
(cond
((pair X) (pack X))
((and (= "-" X) (format (peek)))
(- (read)) )
(T X) ) ) ) ) )
 
(de printJson (Item) # For simplicity, without indentation
(cond
((atom Item) (if Item (print @) (prin "{}")))
((=T (car Item))
(prin "[")
(map
'((X)
(printJson (car X))
(and (cdr X) (prin ", ")) )
(cdr Item) )
(prin "]") )
(T
(prin "{")
(map
'((X)
(print (caar X))
(prin ": ")
(printJson (cdar X))
(and (cdr X) (prin ", ")) )
Item )
(prin "}") ) ) )

This reads/prints JSON from/to files, pipes, sockets etc. To read from a string, a pipe can be used:

: (pipe (prinl "{ \"foo\": 1, \"bar\": [10, \"apples\"] }")
   (readJson) )
-> (("foo" . 1) ("bar" T 10 "apples"))

: (printJson
   (quote
      ("name" . "Smith")
      ("age" . 25)
      ("address"
         ("street" . "21 2nd Street")
         ("city" . "New York")
         ("state" . "NY")
         ("zip" . "10021") )
      ("phone" T "212 555-1234" "646 555-4567") ) )
{"name": "Smith", "age": 25, ... {"street": ... "phone": ["212 555-1234", ...

[edit] Pike

int main() {
// Decoding
string json = "{\"cake\":[\"desu\",1,2.3],\"foo\":1}";
write("%O\n", Standards.JSON.decode(json));
 
// Encoding
mapping m = ([
"foo": ({ 1, 2, 3 }),
"bar": "hello"
]);
 
write("%s\n", Standards.JSON.encode(m));
}
([ /* 2 elements */
  "cake": ({ /* 3 elements */
        "desu",
        1,
        2.3
    }),
  "foo": 1
])
{"foo":[1,2,3],"bar":"hello"}

[edit] Python

Works with: Python version 2.6+
Works with: Python version 3.0+
>>> import json
>>> data = json.loads('{ "foo": 1, "bar": [10, "apples"] }')
>>> sample = { "blue": [1,2], "ocean": "water" }
>>> json_string = json.dumps(sample)
>>> json_string
'{"blue": [1, 2], "ocean": "water"}'
>>> sample
{'blue': [1, 2], 'ocean': 'water'}
>>> data
{'foo': 1, 'bar': [10, 'apples']}

Because most of JSON is valid Python syntax (except "true", "false", and "null", and a few obscure escape sequences), it is also possible (but not recommended) to parse JSON using eval():

>>> true = True; false = False; null = None
>>> data = eval('{ "foo": 1, "bar": [10, "apples"] }')
>>> data
{'foo': 1, 'bar': [10, 'apples']}

[edit] R

library(rjson)
data <- fromJSON('{ "foo": 1, "bar": [10, "apples"] }')
data
data
$foo
[1] 1

$bar
$bar[[1]]
[1] 10

$bar[[2]]
[1] "apples"
cat(toJSON(data))
{"foo":1,"bar":[10,"apples"]}

[edit] Racket

 
#lang racket
 
(require json)
 
(string->jsexpr
"{\"foo\":[1,2,3],\"bar\":null,\"baz\":\"blah\"}")
 
(write-json '(1 2 "three" #hash((x . 1) (y . 2) (z . 3))))
 

[edit] REBOL

Using json.org/json.r

json-str: {{"menu": {
"id": "file",
"string": "File:",
"number": -3,
"boolean": true,
"boolean2": false,
"null": null,
"array": [1, 0.13, null, true, false, "\t\r\n"],
"empty-string": ""
}
}}
 
res: json-to-rebol json-str
js: rebol-to-json res
 

json-to-rebol Result:

make object! [
    menu: make object! [
        id: "file"
        string: "File:"
        number: -3
        boolean: true
        boolean2: false
        null: none
        array: [1 0.13 none true false "^-^M^/"]
        empty-string: ""
    ]
]


rebol-to-json Result:

{
    "menu": {
        "id": "file",
        "string": "File:",
        "number": -3,
        "boolean": true,
        "boolean2": false,
        "null": null,
        "array": [1, 0.13, null, true, false, "\t\r\n"],
        "empty-string": ""
    }
}

[edit] Ruby

Uses
Library: RubyGems
package json
require 'json'
ruby_obj = JSON.parse('{"blue": [1, 2], "ocean": "water"}')
p ruby_obj
puts ruby_obj.class
puts ruby_obj["blue"].class
ruby_obj["ocean"] = {"water" => %w{fishy salty}}
puts JSON.generate(ruby_obj)

Outputs

{"blue"=>[1, 2], "ocean"=>"water"}
Hash
Array
{"blue":[1,2],"ocean":{"water":["fishy","salty"]}}

[edit] Scala

Using the builtin parsing lib (debatably slower than third-party libs such as lift-json from Liftweb).

scala> import scala.util.parsing.json.{JSON, JSONObject}
import scala.util.parsing.json.{JSON, JSONObject}
 
scala> JSON.parseFull("""{"foo": "bar"}""")
res0: Option[Any] = Some(Map(foo -> bar))
 
scala> JSONObject(Map("foo" -> "bar")).toString()
res1: String = {"foo" : "bar"}
 

[edit] Smalltalk

Use the NeoJSON library: NeoJSON

 
NeoJSONReader fromString: '{ "foo": 1, "bar": [10, "apples"] }'.
 

Output:

a Dictionary('bar'->#(10 'apples') 'foo'->1 )

[edit] Tcl

For parsing JSON,
Library: Tcllib (Package: json)
provides the capability (see the Tcler's Wiki page on it for more discussion):
package require json
set sample {{ "foo": 1, "bar": [10, "apples"] }}
 
set parsed [json::json2dict $sample]
puts $parsed

Output:

foo 1 bar {10 apples}

However, that package is very weak in its generation of JSON because Tcl's official type system is substantially different to that envisaged by JSON. It's possible to work around this though the use of Tcl 8.6, as this next example shows:

Works with: Tcl version 8.6
package require Tcl 8.6
 
proc tcl2json value {
# Guess the type of the value; deep *UNSUPPORTED* magic!
regexp {^value is a (.*?) with a refcount} \
[::tcl::unsupported::representation $value] -> type
 
switch $type {
string {
# Skip to the mapping code at the bottom
}
dict {
set result "{"
set pfx ""
dict for {k v} $value {
append result $pfx [tcl2json $k] ": " [tcl2json $v]
set pfx ", "
}
return [append result "}"]
}
list {
set result "\["
set pfx ""
foreach v $value {
append result $pfx [tcl2json $v]
set pfx ", "
}
return [append result "\]"]
}
int - double {
return [expr {$value}]
}
booleanString {
return [expr {$value ? "true" : "false"}]
}
default {
# Some other type; do some guessing...
if {$value eq "null"} {
# Tcl has *no* null value at all; empty strings are semantically
# different and absent variables aren't values. So cheat!
return $value
} elseif {[string is integer -strict $value]} {
return [expr {$value}]
} elseif {[string is double -strict $value]} {
return [expr {$value}]
} elseif {[string is boolean -strict $value]} {
return [expr {$value ? "true" : "false"}]
}
}
}
 
# For simplicity, all "bad" characters are mapped to \u... substitutions
set mapped [subst -novariables [regsub -all {[][\u0000-\u001f\\""]} \
$value {[format "\\\\u%04x" [scan {& } %c]]}]]
return "\"$mapped\""
}

Sample code (note that the value is built with dict create and list so that there is some auxiliary type hints available, which the above procedure can read):

set d [dict create blue [list 1 2] ocean water]
puts [tcl2json $d]

Output:

{"blue": [1, 2], "ocean": "water"}

Note that this is capable of correctly handling the round-trip of values parsed from the json package described above.

[edit] TXR

[edit] Parsing

The following implements the parsing half of the task. It is a parser closely based on the JSON grammar [[1]].

It is implemented with recursive horizontal pattern matching functions, and so basically the definition resembles a grammar. Horizontal functions are a new feature in TXR, and basically allow the language to easily specify LL grammars with indefinite lookahead, not restricted to regular languages (thanks to TXR's backtracking). The numerous occurences of @\ in the code are line continuations. Horizontal functions must be written on one logical line. @\ eats the whitespace at the start of the next physical line, to allow indentation.

The parser translates to a nested list structure in which the types are labeled with the strings "O", "A", "N", "S" and "K". (Object, array, number, string, and keyword).

The largest grammar rule handles JSON string literals. The strategy is to generate a HTML string and then filter from HTML using the :from_html filter in TXR. For instance \uABCD is translated to &#xABCD; and then the filter will produce the proper Unicode character. Similarly \" is translated to &quot; and \n is translated to etc.

A little liberty is taken: the useless commas in JSON are treated as optional.

Superfluous terminating commas (not generated by the JSON grammar but accepted by some other parsers) are not allowed by this parser.

@(define value (v))@\
@(cases)@\
@(string v)@(or)@(num v)@(or)@(object v)@(or)@\
@(keyword v)@(or)@(array v)@\
@(end)@\
@(end)
@(define ws)@/[\n\t ]*/@(end)
@(define string (g))@\
@(local s hex)@\
@(ws)@\
"@(coll :gap 0 :vars (s))@\
@(cases)@\
\"@(bind s "&quot;")@(or)@\
\\@(bind s "\\\\")@(or)@\
\/@(bind s "\\/")@(or)@\
\b@(bind s "&#8;")@(or)@\
\f@(bind s "&#12;")@(or)@\
\n@(bind s "&#10;")@(or)@\
\r@(bind s "&#13;")@(or)@\
\t@(bind s "&#9;")@(or)@\
\u@{hex /[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]/}@\
@(bind s `&#x@hex;`)@(or)@\
@{s /[^"\\]*/}@(filter :to_html s)@\
@(end)@\
@(until)"@\
@(end)"@\
@(ws)@\
@(cat s "")@\
@(filter :from_html s)@\
@(bind g ("S" s))@\
@(end)
@(define num (v))@\
@(local n)@\
@(ws)@{n /-?[0-9]+((\.[0-9]+)?([Ee][+\-]?[0-9]+)?)?/}@(ws)@\
@(bind v ("N" n))@\
@(end)
@(define keyword (v))@\
@(local k)@\
@(all)@(ws)@{k /true|false|null/}@(trailer)@/[^A-Za-z0-9_]/@(end)@(ws)@\
@(bind v ("K" k))@\
@(end)
@(define object (v))@\
@(local p e pair)@\
@(ws){@(ws)@(coll :gap 0 :vars (pair))@\
@(string p):@(value e)@/,?/@\
@(bind pair (p e))@\
@(until)}@\
@(end)}@(ws)@\
@(bind v ("O" pair))@\
@(end)
@(define array (v))@\
@(local e)@\
@(ws)[@(ws)@(coll :gap 0 :var (e))@(value e)@/,?/@(until)]@(end)]@(ws)@\
@(bind v ("A" e))@\
@(end)
@(freeform)
@(maybe)@(value v)@(end)@badsyntax

A few tests. Note, the badsyntax variable is bound to any trailing portion of the input that does not match the syntax. The call to the parser @(value v) extracts the longest prefix of the input which is consistent with the syntax, leaving the remainder to be matched into badsyntax.

$ echo  -n '{ "a" : { "b" : 3, "c" : [1,2,3] }  }[' | ./txr -l json.txr - 
(v "O" ((("S" "a") ("O" ((("S" "b") ("N" "3")) (("S" "c") ("A" (("N" "1") ("N" "2") ("N" "3")))))))))
(badsyntax . "[\n")
 
$ echo -n '"\u1234"' | ./txr -l json.txr -
(v "S" "\11064")
(badsyntax . "")
Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox