JSON Processing

Content:

  1. Introduction
  2. Examples
  3. Object tree
  4. Class binding
  5. Hybrid

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 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);
    }
}

.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.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));
        }
    }
}

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_AddItemReferenceToArray(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

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

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.

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));
    }
}

.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));
        }
    }
}

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__)

Article history:

Version Date Description
1.0 May 25th 2019 Initial version
1.1 May 27th 2019 Add Delphi/Lazarus and C

Other articles:

See list of all articles here

Comments:

Please send comments to Arne Vajhøj