JSON Processing

Content:

  1. Introduction
  2. Examples
  3. Object tree
  4. Class binding
  5. Hybrid
  6. Stream reading
  7. Stream writing

Introduction:

JSON (JavaScript Object Notation) is data format.

Despite its name it is used from almost all languages not just JavaScript.

It is widely used for all sort sof data.

It was invented by Douglas Crockford in 2001. It is standardized in ECMA-404 (2013) and RFC 7158/7159/8259 (2013/2014/2017).

This article will assume the reader knows the format.

Most modern programming languages and runtimes have good support for JSON.

Examples:

In the following sections we will see various techniques to read, update and write JSON using various programming languages and JSON libraries.

The examples will use the following super simple JSON:

[ { "no" : 1, "name" : "Alan A", "role" : "Manager" }, { "no" : 2, "name" : "Brian B", "role" : "Engineer" }, { "no" : 3, "name" : "Chris C", "role" : "Sales rep" } ]

The C examples will be shown in simple - possible a bit oldfashioned - C. I will expect examples to work with C 89 compliant compilers.

Object tree:

One type of JSON libraries work on generic JSON types JsonArray and JsonObject and access data via numeric indexes and named fields.

This sort of representation does not require any known classes to be defined, but tend to be a bit cumbersome to write.

Java SE does not come with a JSON library, so Java developers have had to look for an external library for many years.

One of the most widely used Java JSON libraries is Google GSON. It was released as open source by Google in 2008.

It is available here.

package jsonproc;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

public class TreeGSON {
    private static final String json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                         "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                         "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
    public static void main(String[] args) {
        JsonParser gson = new JsonParser();
        // iterate over all employees
        JsonArray employees = gson.parse(json).getAsJsonArray();
        for(int i = 0; i < employees.size(); i++) {
            JsonObject employee = employees.get(i).getAsJsonObject();
            // find no, name and role
            int no = employee.get("no").getAsInt();
            String name = employee.get("name").getAsString();
            String role = employee.get("role").getAsString();
            // print
            System.out.println("no=" + no);
            System.out.println("name=" + name);
            System.out.println("role=" + role);
        }
        // add employee
        JsonObject newemployee = new JsonObject();
        newemployee.addProperty("no", 4);
        newemployee.addProperty("name", "Dave D");
        newemployee.addProperty("role", "Intern");
        employees.add(newemployee);
        // write out
        System.out.println(employees.toString());
    }
}

Java EE 8 released in 2017 introduced the JSON-P (JSR 353) API.

And despite being part of Java EE then it can be used by Java SE applications.

package jsonproc;

import java.io.StringReader;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonWriter;

public class TreeJSONP {
    private static final String json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                         "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                         "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
    public static void main(String[] args) {
        // iterate over all employees
        JsonReader jr = Json.createReader(new StringReader(json));
        JsonArray employees = jr.readArray();
        for(int i = 0; i < employees.size(); i++) {
            JsonObject employee = employees.getJsonObject(i);
            // find no, name and role
            int no = employee.getInt("no");
            String name = employee.getString("name");
            String role = employee.getString("role");
            // print
            System.out.println("no=" + no);
            System.out.println("name=" + name);
            System.out.println("role=" + role);
        }
        // Note: JsonArray is immutable so it is not possible to add an employee (JSON-P does have the ability to create JSON from scratch)
        // write out
        JsonWriter jw = Json.createWriter(System.out);
        jw.writeArray(employees);
    }
}

Jackson is one of the most widely used JSON libraries for Java. Maybe not so much for manual reading/writing, but definitely under the hood for RESTful web services.

package jsonproc;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class TreeJackson {
    private static final String json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                         "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                         "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
    public static void main(String[] args) throws JsonMappingException, JsonProcessingException {
        ObjectMapper om = new ObjectMapper();
        // iterate over all employees
        JsonNode employees = om.readTree(json);
        for(int i = 0; i < employees.size(); i++) {
            JsonNode employee = employees.get(i);
            // find no, name and role
            int no = employee.get("no").asInt();
            String name = employee.get("name").asText();
            String role = employee.get("role").asText();
            // print
            System.out.println("no=" + no);
            System.out.println("name=" + name);
            System.out.println("role=" + role);
        }
        // add employee
        ObjectNode newemployee = om.createObjectNode();
        newemployee.put("no", 4);
        newemployee.put("name", "Dave D");
        newemployee.put("role", "Intern");
        ((ArrayNode)employees).add(newemployee);
        // write out
        System.out.println(om.writeValueAsString(employees));
    }
}

.NET Framework 3.5 released in 2007 added the System.Web.Script.Serialization namespace to ASP.NET and it is usuable from any .NET application.

Note that Microsoft recommends using NewtonSoft JSON.NET instead.

using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;

namespace JsonProc.TreeBuiltin
{                                                                                                                                      
    public class Program
    {
        private const string json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                      "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                      "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
        public static void Main(string[] args)
        {
            JavaScriptSerializer ser = new JavaScriptSerializer();
            // iterate over all employees
            object[] employees = (object[])ser.DeserializeObject(json);
            foreach(IDictionary<string, object> employee in employees)
            {
                // find no, name and role
                int no = (int)employee["no"];
                string name = (string)employee["name"];
                string role = (string)employee["role"];
                // print
                Console.WriteLine(no);
                Console.WriteLine(name);
                Console.WriteLine(role);
            }
            // add employee
            IDictionary<string, object> newemployee = new Dictionary<string, object>();
            newemployee["no"] = 4;
            newemployee["name"] = "Dave D";
            newemployee["role"] = "Intern";
            Array.Resize(ref employees, 4);
            employees[3] = newemployee;
            // write out
            Console.WriteLine(ser.Serialize(employees));
        }
    }
}

NewtonSoft JSON.NET is a very widely used JSON library for .NET that was first released in 2006.

Its homepage is here here. It is available as open source and the easiest way to get it is via NuGet.

using System;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace JsonProc.TreeNewton
{
    public class Program
    {
        private const string json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                    "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                    "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
        public static void Main(string[] args)
        {
            // iterate over all employees
            JArray employees = (JArray)JsonConvert.DeserializeObject(json);
            foreach(JObject employee in employees)
            {
                // find no, name and role
                int no = (int)employee["no"];
                string name = (string)employee["name"];
                string role = (string)employee["role"];
                // print
                Console.WriteLine(no);
                Console.WriteLine(name);
                Console.WriteLine(role);
            }
            // add employee
            JObject newemployee = new JObject();
            newemployee["no"] = 4;
            newemployee["name"] = "Dave D";
            newemployee["role"] = "Intern";
            employees.Add(newemployee);
            // write out
            Console.WriteLine(JsonConvert.SerializeObject(employees));
        }
    }
}

.NET Core 3.0 released in 2019 added the System.Text.Json namespace with basic JSON functionality.

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace JsonProc.TreeCore
{
    public class Program
    {
        private const string json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                    "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                    "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
        public static void Main(string[] args)
        {
            // iterate over all employees
            using(JsonDocument employees = JsonDocument.Parse(json))
            {
                foreach(JsonElement employee in employees.RootElement.EnumerateArray())
                {
                    // find no, name and role
                    int no = employee.GetProperty("no").GetInt32();
                    string name = employee.GetProperty("name").GetString();
                    string role = employee.GetProperty("role").GetString();
                    // print
                    Console.WriteLine(no);
                    Console.WriteLine(name);
                    Console.WriteLine(role);
                }
                // add employee
                // **** not possible as JsonDocument is immutable ****
                // write out
                Console.WriteLine(employees.RootElement);
            }
        }
    }
}

There are severeal JSON libraries available for C. This example use the cJSON library.

The cJSON library is very simple - it is really just one .h and one .c file. It is open source available from here.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cJSON.h"

#define JSON "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " \
               "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " \
               "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]"

int main()
{
    cJSON *employees, *employee, *newemployee;
    char *s, *name, *role;
    int i, no;
    /* iterate over all employees */
    employees = cJSON_Parse(JSON);
    for(i = 0; i < cJSON_GetArraySize(employees); i++)
    {
        employee = cJSON_GetArrayItem(employees, i);
        /* find no, name and role */
        no = cJSON_GetObjectItem(employee, "no")->valueint;
        name = cJSON_GetObjectItem(employee, "name")->valuestring;
        role = cJSON_GetObjectItem(employee, "role")->valuestring;
        /* print */
        printf("no = %d\n", no);
        printf("name = %s\n", name);
        printf("role = %s\n", role);
    }
    /* add employee */
    newemployee = cJSON_CreateObject();
    cJSON_AddItemToObject(newemployee, "no",  cJSON_CreateNumber(4));
    cJSON_AddItemToObject(newemployee, "name",  cJSON_CreateString("Dave D"));
    cJSON_AddItemToObject(newemployee, "role",  cJSON_CreateString("Intern"));
    cJSON_AddItemToArray(employees, newemployee);
    /* write out */
    s = cJSON_PrintUnformatted(employees);
    printf("%s\n", s);
    free(s);
    /* */
    cJSON_Delete(employees);
    return 0;
}

Build with GCC on Windows:

gcc -Wall %1.c cJSON.c -o %1.exe

Build on VMS:

$ cc/warn=disable:LONGEXTERN cJSON
$ cc 'p1'
$ link 'p1' + cJSON

There are severeal JSON libraries available for C. This example use the jansson library.

The jansson library is widely used. It is open source and available from here.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "jansson.h"

#define JSON "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " \
               "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " \
               "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]"

int main()
{
    json_t *employees, *employee, *newemployee;
    json_error_t error;
    const char *name, *role;
    char *s;
    int i, no;
    /* iterate over all employees */
    employees = json_loads(JSON, 0, &error);
    if(!employees)
    {
        printf("Error: %s\n", error.text);
    }
    for(i = 0; i < json_array_size(employees); i++)
    {
        employee = json_array_get(employees, i);
        /* find no, name and role */
        no =  json_integer_value(json_object_get(employee, "no"));
        name =  json_string_value(json_object_get(employee, "name"));
        role =  json_string_value(json_object_get(employee, "role"));
        /* print */
        printf("no = %d\n", no);
        printf("name = %s\n", name);
        printf("role = %s\n", role);
    }
    /* add employee */
    newemployee = json_object();
    json_object_set(newemployee, "no", json_integer(4));
    json_object_set(newemployee, "name", json_string("Dave D"));
    json_object_set(newemployee, "role", json_string("Intern"));
    json_array_append(employees, newemployee);
    /* write out */
    s = json_dumps(employees, 0);
    printf("%s\n", s);
    free(s);
    /* */
    json_decref(employees);
    return 0;
}

Build with GCC on Windows:

gcc -m32 -Wall -I%JANSSON%\include -L%JANSSON%\lib %1.c -ljansson -o %1.exe

There are severeal JSON libraries available for C. This example use the simple library json-parser and json-builder.

Parse example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "json.h"

#define JSON "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " \
               "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " \
               "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]"

int main()
{
    json_value *employees, *employee;
    char *name, *role;
    int i, j, no;
    /* iterate over all employees */
    employees = json_parse(JSON, strlen(JSON));
    for(i = 0; i < employees->u.array.length; i++)
    {
        employee = employees->u.array.values[i];
        /* find no, name and role */
        for(j = 0; j < employee->u.object.length; j++)
        {
            if(strcmp(employee->u.object.values[j].name, "no") == 0)
            {
                no = employee->u.object.values[j].value->u.integer;
            }
            if(strcmp(employee->u.object.values[j].name, "name") == 0)
            {
                name = employee->u.object.values[j].value->u.string.ptr;
            }
            if(strcmp(employee->u.object.values[j].name, "role") == 0)
            {
                role = employee->u.object.values[j].value->u.string.ptr;
            }
        }
        /* print */
        printf("no = %d\n", no);
        printf("name = %s\n", name);
        printf("role = %s\n", role);
    }
    /* */
    json_value_free(employees);
    return 0;
}

Build with GCC on Windows:

gcc -Wall -Wno-pointer-to-int-cast Tree_Simple.c json.c -o Tree.exe

Build on VMS:

$ cc json
$ cc Tree_Simple
$ link Tree_simple + json

Parse and build example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "json-builder.h"

#define JSON "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " \
               "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " \
               "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]"

int main()
{
    json_value *employees, *employee, *newemployee;
    char *s, *name, *role;
    int i, j, no;
    char error[128];
    /* iterate over all employees */
    json_settings settings = {};
    settings.value_extra = json_builder_extra;
    employees = json_parse_ex(&settings, JSON, strlen(JSON), error);
    for(i = 0; i < employees->u.array.length; i++)
    {
        employee = employees->u.array.values[i];
        /* find no, name and role */
        for(j = 0; j < employee->u.object.length; j++)
        {
            if(strcmp(employee->u.object.values[j].name, "no") == 0)
            {
                no = employee->u.object.values[j].value->u.integer;
            }
            if(strcmp(employee->u.object.values[j].name, "name") == 0)
            {
                name = employee->u.object.values[j].value->u.string.ptr;
            }
            if(strcmp(employee->u.object.values[j].name, "role") == 0)
            {
                role = employee->u.object.values[j].value->u.string.ptr;
            }
        }
        /* print */
        printf("no = %d\n", no);
        printf("name = %s\n", name);
        printf("role = %s\n", role);
    }
    /* add employee */
    newemployee = json_object_new(0);
    json_object_push(newemployee, "no", json_integer_new(4));
    json_object_push(newemployee, "name", json_string_new("Dave D"));
    json_object_push(newemployee, "role", json_string_new("Intern"));
    json_array_push(employees, newemployee);
    /* write out */
    s = malloc(json_measure(employees));
    json_serialize(s, employees);
    printf("%s\n", s);
    free(s);
    /* */
    json_builder_free(employees);
    return 0;
}

Build with GCC on Windows:

gcc -Wall -Wno-pointer-to-int-cast -I. Tree_SimpleX.c json.c json-builder.c -o Tree.exe

Build on VMS:

$ cc json
$ cc/include=[] json-builder
$ cc/include=[]/warn=disable:emptyinit Tree_SimpleX
$ link Tree_SimpleX + json + json-builder

Both Delphi and Lazarus come with builtin support for JSON.

The code below is tested with Lazarus, but I believe it is only the uses clause that need to be changed for Delphi.

program Tree;

uses
  fpjson, jsonparser;

const
  json = '[ { "no" : 1, "name" : "Alan A", "role" : "Manager" }, ' +
           '{ "no" : 2, "name" : "Brian B", "role" : "Engineer" }, ' +
           '{ "no" : 3, "name" : "Chris C", "role" : "Sales rep" } ]';
var
  employees : TJSONArray;
  employee, newemployee : TJSONObject;
  name, role : string;
  no, i : integer;

begin
  (* iterate over all employees *)
  employees := TJSONArray(GetJSON(json));
  for i := 0 to employees.Count - 1 do begin
    employee := TJSONObject(employees.Items[i])
    (* find no, name and role *);
    no := employee.Integers['no'];
    name := employee.Strings['name'];
    role := employee.Strings['role'];
    (* print *)
    writeln('no = ', no);
    writeln('name = ', name);
    writeln('role = ', role);
  end;
  (* add employee *)
  newemployee := TJSONObject.Create;
  newemployee.Add('no', 4);
  newemployee.Add('name', 'Dave D');
  newemployee.Add('role', 'Intern');
  employees.Add(newemployee);
  (* write out *)
  writeln(employees.AsJSON);
  employees.Free;
end.
program TreeFundamentals;

uses
  flcJSON;

const
  json = '[ { "no" : 1, "name" : "Alan A", "role" : "Manager" }, ' +
           '{ "no" : 2, "name" : "Brian B", "role" : "Engineer" }, ' +
           '{ "no" : 3, "name" : "Chris C", "role" : "Sales rep" } ]';

var
  parser : TJSONParser;
  employees : TJSONArray;
  employee, newemployee : TJSONObject;
  name, role : widestring;
  no, i : integer;

begin
  parser := TJSONParser.Create();
  (* iterate over all employees *)
  employees := TJSONArray(parser.ParseText(json));
  for i := 0 to employees.Count - 1 do begin
     employee := TJSONObject(employees.Item[i]);
     (* find no, name and role *);
     no := employee.Item['no'].ValueInt;
     name := employee.Item['name'].ValueStr;
     role := employee.Item['role'].ValueStr;
     (* print *)
     writeln('no = ', no);
     writeln('name = ', name);
     writeln('role = ', role);
  end;
    (* add employee *)
  newemployee := TJSONObject.Create;
  newemployee.Add('no', TJSONInteger.Create(4));
  newemployee.Add('name', TJSONString.Create('Dave D'));
  newemployee.Add('role', TJSONString.Create('Intern'));
  employees.Append(newemployee);
  (* write out *)
  writeln(employees.GetJsonString());
  (* *)
  parser.Free;
end.


Class binding:

Another type of JSON libraries work by binding (mapping) class definitions to JSON structures.

This sort of representation require use of defined classes to be defined, but are very convenient to use.

Java SE does not come with a JSON library, so Java developers have had to look for an external library for many years.

One of the most widely used Java JSON libraries is Google GSON. It was released as open source by Google in 2008.

It is available here.

package jsonproc;

public class Employee {
    private int no;
    private String name;
    private String role;
    public Employee() {
        this(0, null, null);
    }
    public Employee(int no, String name, String role) {
        this.no = no;
        this.name = name;
        this.role = role;
    }
    public int getNo() {
        return no;
    }
    public void setNo(int no) {
        this.no = no;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
    public String toString() {
        return String.format("[%d,%s,%s]", no, name, role);
    }
}
package jsonproc;

import com.google.gson.Gson;

public class BindGSON {
    private static final String json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                         "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                         "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
    public static void main(String[] args) {
        Gson gson = new Gson();
        // read
        Employee[] employees = gson.fromJson(json, Employee[].class);
        for(Employee employee : employees) {
            System.out.println(employee);
        }
        // write
        System.out.println(gson.toJson(employees));
    }
}

Java EE released in 2017 introduced the JSON-B (JSR 367) API.

And despite being part of Java EE then it can be used by Java SE applications.

package jsonproc;

public class Employee {
    private int no;
    private String name;
    private String role;
    public Employee() {
        this(0, null, null);
    }
    public Employee(int no, String name, String role) {
        this.no = no;
        this.name = name;
        this.role = role;
    }
    public int getNo() {
        return no;
    }
    public void setNo(int no) {
        this.no = no;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
    public String toString() {
        return String.format("[%d,%s,%s]", no, name, role);
    }
}
package jsonproc;

import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;

public class BindJSONB {
    private static final String json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                         "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                         "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
    public static void main(String[] args) {
        Jsonb b = JsonbBuilder.create();
        // read
        Employee[] employees = b.fromJson(json, Employee[].class);
        for(Employee employee : employees) {
            System.out.println(employee);
        }
        // write
        System.out.println(b.toJson(employees));
    }
}

Jackson is one of the most widely used JSON libraries for Java. Maybe not so much for manual reading/writing, but definitely under the hood for RESTful web services.

package jsonproc;

public class Employee {
    private int no;
    private String name;
    private String role;
    public Employee() {
        this(0, null, null);
    }
    public Employee(int no, String name, String role) {
        this.no = no;
        this.name = name;
        this.role = role;
    }
    public int getNo() {
        return no;
    }
    public void setNo(int no) {
        this.no = no;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
    public String toString() {
        return String.format("[%d,%s,%s]", no, name, role);
    }
}
package jsonproc;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class BindJackson {
    private static final String json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                         "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                         "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
    public static void main(String[] args) throws JsonMappingException, JsonProcessingException {
        ObjectMapper om = new ObjectMapper();
        // read
        Employee[] employees = om.readValue(json, Employee[].class);
        for(Employee employee : employees) {
            System.out.println(employee);
        }
        // write
        System.out.println(om.writeValueAsString(employees));
    }
}

.NET 3.5 released in 2007 added the System.Web.Script.Serialization namespace to ASP.NET and it is usuable from any .NET application.

Note that Microsoft recommends using NewtonSoft JSON.NET instead.

using System;
using System.Web.Script.Serialization;

namespace JsonProc.BindBuiltin
{
    public class Employee
    {
        public Employee() : this(0, "", "")
        {
        }
        public Employee(int no, string name, string role)
        {
            this.No = no;
            this.Name = name;
            this.Role = role;            
        }
        public int No { get; set; }
        public string Name { get; set; }
        public string Role { get; set; }
        public override string ToString()
        {
            return string.Format("[{0},{1},{2}]", No, Name, Role);
        }

    }
    public class Program
    {
       private const string json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                     "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                     "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
        public static void Main(string[] args)
        {
            // read
            JavaScriptSerializer ser = new JavaScriptSerializer();
            Employee[] employees = (Employee[])ser.Deserialize(json, typeof(Employee[]));
            foreach(Employee employee in employees)
            {
                Console.WriteLine(employee);
            }
            // write
            Console.WriteLine(ser.Serialize(employees));
        }
    }
}

NewtonSoft JSON.NET is a very widely used JSON library for .NET that was first released in 2006.

Its homepage is here here. It is available as open source and the easiest way to get it is via NuGet.

using System;

using Newtonsoft.Json;

namespace JsonProc.BindNewton
{
    public class Employee
    {
        public Employee() : this(0, "", "")
        {
        }
        public Employee(int no, string name, string role)
        {
            this.No = no;
            this.Name = name;
            this.Role = role;
        }
        public int No { get; set; }
        public string Name { get; set; }
        public string Role { get; set; }
        public override string ToString()
        {
            return string.Format("[{0},{1},{2}]", No, Name, Role);
        }

    }
    public class Program
    {
        private const string json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                    "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                    "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
        public static void Main(string[] args)
        {
            // read
            Employee[] employees = JsonConvert.DeserializeObject<Employee[]>(json);
            foreach (Employee employee in employees)
            {
                Console.WriteLine(employee);
            }
            // write
            Console.WriteLine(JsonConvert.SerializeObject(employees));
        }
    }
}

.NET Core 3.0 released in 2019 added the System.Text.Json namespace with basic JSON functionality.

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace JsonProc.BindCore
{
    public class Employee
    {
        public Employee() : this(0, "", "")
        {
        }
        public Employee(int no, string name, string role)
        {
            this.No = no;
            this.Name = name;
            this.Role = role;
        }
        public int No { get; set; }
        public string Name { get; set; }
        public string Role { get; set; }
        public override string ToString()
        {
            return string.Format("[{0},{1},{2}]", No, Name, Role);
        }

    }
    public class Program
    {
        private const string json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                    "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                    "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
        public static void Main(string[] args)
        {
            JsonSerializerOptions opts = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; // we will use non-capitalized attribute names
            // read
            Employee[] employees = JsonSerializer.Deserialize<Employee[]>(json, opts);
            foreach (Employee employee in employees)
            {
                Console.WriteLine(employee);
            }
            // write
            Console.WriteLine(JsonSerializer.Serialize(employees, opts));
        }
    }
}

Jil is a JSON parser with focus on parsing speed. It is open source and available via NuGet.

using System;
using Jil;

namespace JsonProc.BindJil
{
    public class Employee
    {
        public Employee() : this(0, "", "")
        {
        }
        public Employee(int no, string name, string role)
        {
            this.No = no;
            this.Name = name;
            this.Role = role;
        }
        public int No { get; set; }
        public string Name { get; set; }
        public string Role { get; set; }
        public override string ToString()
        {
            return string.Format("[{0},{1},{2}]", No, Name, Role);
        }

    }
    public class Program
    {
        private const string json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                    "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                    "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
        public static void Main(string[] args)
        {
            // read
            Employee[] employees = JSON.Deserialize<Employee[]>(json, Options.CamelCase);
            foreach (Employee employee in employees)
            {
                Console.WriteLine(employee);
            }
            // write
            Console.WriteLine(JSON.Serialize(employees, Options.CamelCase));
        }
    }
}

Hybrid:

JSON libraries for dynamically typed languages usually works a bit different by utilizing their dynamic nature. The result is a sort of hybrid between the tree approach and the binding approach.

When parsing they can generate objects with dynamically added properties. And when generating they can treat all objects with same properties the same way.

It is possible to have a mix of objects of unknown class and objects of known class and treat them identical as long they have the same properties.

PHP comes with builtin json_decode and json_encode functions.

<?php
class Employee {
    public $no;
    public $name;
    public $role;
    public function __construct($no, $name, $role) {
        $this->no = $no;
        $this->name = $name;
        $this->role = $role;
    }
}

$json = '[ { "no" : 1, "name" : "Alan A", "role" : "Manager" }, ' .
          '{ "no" : 2, "name" : "Brian B", "role" : "Engineer" }, ' .
          '{ "no" : 3, "name" : "Chris C", "role" : "Sales rep" } ]';
// iterate over all employees
$employees = json_decode($json);
foreach($employees as $employee) {
    // find no, name and role
    $no = $employee->no;
    $name = $employee->name;                                                                                 
    $role = $employee->role;
    // print
    echo "no = $no\r\n";
    echo "name = $name\r\n";
    echo "role = $role\r\n";
}
// add employee
$employees[] = new Employee(4, 'Dave D', 'Intern');
// write out
echo json_encode($employees);
?>

Python comes with a builton json module.

import json

class Employee(object):
    def __init__(self, _no, _name, _role):
        self.no = _no
        self.name = _name
        self.role = _role

jsonstr = '[ { "no" : 1, "name" : "Alan A", "role" : "Manager" }, ' + \
            '{ "no" : 2, "name" : "Brian B", "role" : "Engineer" }, ' + \
            '{ "no" : 3, "name" : "Chris C", "role" : "Sales rep" } ]';

# iterate over all employees
employees = json.loads(jsonstr)
for employee in employees:
    # find no, name and role
    no = employee['no']
    name = employee['name']
    role = employee['role']
    # print
    print('no = %d' % (no))
    print('name = %s' % (name))
    print('role = %s' % (role))
# add new employee
employees.append(Employee(4, 'Dave D', 'Intern'))
# write out
print json.dumps(employees, default = lambda o: o.__dict__)

Stream reading:

Stream reading allows reading JSON sequentially without having all JSON in memory.

It is very efficient but can also be a bit cumbersome to use.

Java EE 8 released in 2017 introduced the JSON-P (JSR 353) API.

And despite being part of Java EE then it can be used by Java SE applications.

package jsonproc;

import java.io.StringReader;

import javax.json.Json;
import javax.json.stream.JsonParser;

public class StreamReaderJSONP {
    private static final String json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                         "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                         "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
    public static void main(String[] args) {
        // open file
        JsonParser parser = Json.createParser(new StringReader(json));
        // process file
        String key = "";
        int no = 0;
        String name = "";
        String role = "";
        while (parser.hasNext()) {
            switch(parser.next()) {
                case START_ARRAY:
                    // nothing
                    break;
                case START_OBJECT:
                    // nothing
                    break;
                case KEY_NAME:
                    key = parser.getString();
                    break;
                case VALUE_NUMBER:
                    // found no
                    if(key.equals("no")) {
                        no = parser.getInt();
                    }
                    break;
                case VALUE_STRING:
                    // found name
                    if(key.equals("name")) {
                        name = parser.getString();
                    }
                    // found role
                    if(key.equals("role")) {
                        role = parser.getString();
                    }
                    break;
                case END_OBJECT:
                    // print
                    System.out.println("no=" + no);
                    System.out.println("name=" + name);
                    System.out.println("role=" + role);
                    break;
                case END_ARRAY:
                    // nothing
                    break;
                default:
                    throw new RuntimeException("Unexpected input");
            }
        }
    }
}

Jackson is one of the most widely used JSON libraries for Java. Maybe not so much for manual reading/writing, but definitely under the hood for RESTful web services.

package jsonproc;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;

public class StreamReaderJackson {
    private static final String json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                         "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                         "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
    public static void main(String[] args) throws IOException {
        // open file
        JsonFactory fac = new JsonFactory();
        JsonParser parser = fac.createParser(json);
        // process file
        String key = "";
        int no = 0;
        String name = "";
        String role = "";
        parser.nextToken();
        while (parser.hasCurrentToken()) {
            switch(parser.currentToken()) {
                case START_ARRAY:
                    // nothing
                    break;
                case START_OBJECT:
                    // nothing
                    break;
                case FIELD_NAME:
                    key = parser.getText();
                    break;
                case VALUE_NUMBER_INT:
                    // found no
                    if(key.equals("no")) {
                        no = parser.getIntValue();
                    }
                    break;
                case VALUE_STRING:
                    // found name
                    if(key.equals("name")) {
                        name = parser.getText();
                    }
                    // found role
                    if(key.equals("role")) {
                        role = parser.getText();
                    }
                    break;
                case END_OBJECT:
                    // print
                    System.out.println("no=" + no);
                    System.out.println("name=" + name);
                    System.out.println("role=" + role);
                    break;
                case END_ARRAY:
                    // nothing
                    break;
                default:
                    throw new RuntimeException("Unexpected input");
            }
            parser.nextToken();
        }
        // close file
        parser.close();
    }
}

NewtonSoft JSON.NET is a very widely used JSON library for .NET that was first released in 2006.

Its homepage is here here. It is available as open source and the easiest way to get it is via NuGet.

using System;
using System.IO;

using Newtonsoft.Json;

namespace JsonProc.StreamReaderNewton
{
    public class Program
    {
        private const string json = "[ { \"no\" : 1, \"name\" : \"Alan A\", \"role\" : \"Manager\" }, " +
                                    "{ \"no\" : 2, \"name\" : \"Brian B\", \"role\" : \"Engineer\" }, " +
                                    "{ \"no\" : 3, \"name\" : \"Chris C\", \"role\" : \"Sales rep\" } ]";
        public static void Main(string[] args)
        {
            // open
            using(JsonTextReader jtr = new JsonTextReader(new StringReader(json)))
            {
                // process
                String prop = "";
                int no = 0;
                string name = "";
                string role = "";
                while(jtr.Read())
                {
                    switch(jtr.TokenType)
                    {
                        case JsonToken.StartArray:
                            // nothing
                            break;
                        case JsonToken.StartObject:
                            // nothing
                            break;
                        case JsonToken.PropertyName:
                            prop = (string)jtr.Value;
                            break;
                        case JsonToken.String:
                            // found name
                            if(prop == "name")
                            {
                                name = (string)jtr.Value;
                            }
                            // found role
                            if(prop == "role")
                            {
                                role = (string)jtr.Value;
                            }
                            break;
                        case JsonToken.Integer:
                            // found no
                            if(prop == "no")
                            {
                                no = (int)(long)jtr.Value;
                            }
                            break;
                        case JsonToken.EndObject:
                            // print
                            Console.WriteLine(no);
                            Console.WriteLine(name);
                            Console.WriteLine(role);
                            break;
                        case JsonToken.EndArray:
                            // nothing
                            break;
                    }
                }
            }
        }
    }
}

Stream writing:

Stream writing allows writing JSON sequentially without having all JSON in memory.

It is very efficient but are really just a very thing wrapper around normal IO.

Java EE 8 released in 2017 introduced the JSON-P (JSR 353) API.

And despite being part of Java EE then it can be used by Java SE applications.

package jsonproc;

public class Employee {
    private int no;
    private String name;
    private String role;
    public Employee() {
        this(0, null, null);
    }
    public Employee(int no, String name, String role) {
        this.no = no;
        this.name = name;
        this.role = role;
    }
    public int getNo() {
        return no;
    }
    public void setNo(int no) {
        this.no = no;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
    @Override
    public String toString() {
        return String.format("[%d,%s,%s]", no, name, role);
    }
}
package jsonproc;

import java.util.ArrayList;
import java.util.List;

import javax.json.Json;
import javax.json.stream.JsonGenerator;

public class StreamWriterJSONP {
    public static void main(String[] args) {
        // create employees
        List<Employee> employees = new ArrayList<Employee>();
        employees.add(new Employee(1, "Alan A", "Manager"));
        employees.add(new Employee(2, "Brian B", "Engineer"));
        employees.add(new Employee(3, "Chris C", "Sales rep"));
        employees.add(new Employee(4, "Dave D", "Intern"));
        // write out
        JsonGenerator gen = Json.createGenerator(System.out);
        gen.writeStartArray();
        for(Employee employee : employees) {
            gen.writeStartObject();
            gen.writeKey("no");
            gen.write(employee.getNo());
            gen.writeKey("name");
            gen.write(employee.getName());
            gen.writeKey("role");
            gen.write(employee.getRole());
            gen.writeEnd();
        }
        gen.writeEnd();
        gen.flush();
    }
}

Jackson is one of the most widely used JSON libraries for Java. Maybe not so much for manual reading/writing, but definitely under the hood for RESTful web services.

package jsonproc;

public class Employee {
    private int no;
    private String name;
    private String role;
    public Employee() {
        this(0, null, null);
    }
    public Employee(int no, String name, String role) {
        this.no = no;
        this.name = name;
        this.role = role;
    }
    public int getNo() {
        return no;
    }
    public void setNo(int no) {
        this.no = no;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
    @Override
    public String toString() {
        return String.format("[%d,%s,%s]", no, name, role);
    }
}
package jsonproc;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;

public class StreamWriterJackson {
    public static void main(String[] args) throws IOException {
        // create employees
        List<Employee> employees = new ArrayList<Employee>();
        employees.add(new Employee(1, "Alan A", "Manager"));
        employees.add(new Employee(2, "Brian B", "Engineer"));
        employees.add(new Employee(3, "Chris C", "Sales rep"));
        employees.add(new Employee(4, "Dave D", "Intern"));
        // write out
        JsonFactory fac = new JsonFactory();
        JsonGenerator gen = fac.createGenerator(System.out);
        gen.writeStartArray();
        for(Employee employee : employees) {
            gen.writeStartObject();
            gen.writeNumberField("no", employee.getNo());
            gen.writeStringField("name", employee.getName());
            gen.writeStringField("role", employee.getRole());
            gen.writeEndObject();
        }
        gen.writeEndArray();
        gen.close();
    }
}

NewtonSoft JSON.NET is a very widely used JSON library for .NET that was first released in 2006.

Its homepage is here here. It is available as open source and the easiest way to get it is via NuGet.

using System;
using System.Collections.Generic;
using System.IO;

using Newtonsoft.Json;

namespace JsonProc.StreamWriterNewton
{
    public class Employee
    {
        public Employee() : this(0, "", "")
        {
        }
        public Employee(int no, string name, string role)
        {
            this.No = no;
            this.Name = name;
            this.Role = role;            
        }
        public int No { get; set; }
        public string Name { get; set; }
        public string Role { get; set; }
        public override string ToString()
        {
            return string.Format("[{0},{1},{2}]", No, Name, Role);
        }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            // create employees
            IList<Employee> employees = new List<Employee>();
            employees.Add(new Employee(1, "Alan A", "Manager"));
            employees.Add(new Employee(2, "Brian B", "Engineer"));
            employees.Add(new Employee(3, "Chris C", "Sales rep"));
            employees.Add(new Employee(4, "Dave D", "Intern"));
            // write out
            StringWriter sw = new StringWriter();
            using (JsonTextWriter jtw = new JsonTextWriter(sw))
            {
                jtw.WriteStartArray();
                foreach(Employee employee in employees)
                {
                    jtw.WriteStartObject();
                    jtw.WritePropertyName("no");
                    jtw.WriteValue(employee.No);
                    jtw.WritePropertyName("name");
                    jtw.WriteValue(employee.Name);
                    jtw.WritePropertyName("role");
                    jtw.WriteValue(employee.Role);
                    jtw.WriteEnd();
                }
                jtw.WriteEnd();
            }
            Console.WriteLine(sw.ToString());
        }
    }
}

It is not difficult to create a streaming write API. Here is a starting point.

diy.h:

#define TRUE 1
#define FALSE 0
static int comma = FALSE;

#define json_start_anon_array(fp) fprintf(fp, "%s[", comma ? "," : ""); comma = FALSE
#define json_start_named_array(fp, propnam) fprintf(fp, "%s\"%s\":[", comma ? "," : "", propnam); comma = FALSE
#define json_end_array(fp) fprintf(fp, "]"); comma = TRUE

#define json_start_anon_object(fp) fprintf(fp, "%s{", comma ? "," : ""); comma = FALSE
#define json_start_named_object(fp, propnam) fprintf(fp, "%s\"%s\":{", comma ? "," : "", propnam); comma = FALSE
#define json_end_object(fp) fprintf(fp, "}"); comma = TRUE

#define json_anon_int_value(fp, val) fprintf(fp, "%s%d", comma ? "," : "", val); comma = TRUE
#define json_named_int_value(fp, propnam, val) fprintf(fp, "%s\"%s\":%d", comma ? "," : "", propnam, val); comma = TRUE

#define json_anon_string_value(fp, val) fprintf(fp, "%s\"%s\"", comma ? "," : "", val); comma = TRUE
#define json_named_string_value(fp, propnam, val) fprintf(fp, "%s\"%s\":\"%s\"", comma ? "," : "", propnam, val); comma = TRUE

Example:

#include <stdio.h>

#include "diy.h"

struct employee
{
    int no;
    char *name;
    char *role;
};

int main()
{
    int i;
    struct employee emp[] = { { 1, "Alan A", "Manager" },
                              { 2, "Brian B", "Engineer" },
                              { 3, "Chris C", "Sales rep" },
                              { 4, "Dave D", "Intern" } };
    json_start_anon_array(stdout);
    for(i = 0; i < 4; i++)
    {
        json_start_anon_object(stdout);
        json_named_int_value(stdout, "no", emp[i].no);
        json_named_string_value(stdout, "name", emp[i].name);
        json_named_string_value(stdout, "role", emp[i].role);
        json_end_object(stdout);
    }
    json_end_array(stdout);
    return 0;
}

XML:

For similar examples in XML see XML Processing.

Article history:

Version Date Description
1.0 May 25th 2019 Initial version
1.1 May 27th 2019 Add Delphi/Lazarus and C
1.2 November 13th 2020 Add .NET Core
1.3 January 17th 2021 Add streaming API's
1.4 January 21st 2021 Add more C examples
1.5 June 2nd 2022 Add Jil and Jackson

Other articles:

See list of all articles here

Comments:

Please send comments to Arne Vajhøj