Basics of JSON data format

Do not miss this exclusive book on Binary Tree Problems. Get it now for free.

This article is an introduction to Javascript Object Notation or JSON for short. JSON is an open standard data-interchange format for transmitting data objects in the form of key-value pairs. JSON data is stored in .json files.

Contents:

  • Basic Syntax
  • Data Types
  • JSON Schema
  • Decoding JSON
  • Encoding JSON
  • Applications

Basic Syntax

Although JSON is referred to as Javascript Object Notation, it is language independent, meaning many modern languages have libraries or classes to decode or encode data in .json file formats.

JSON and Javascript are NOT the same.

JSON is a lightweight method of transfering data from servers to then be directly parsed and rendered in browsers. Since most browsers can understand Javascript, it is common for Javascript files to parse incoming JSON data into JS Objects which can be then fed into HTML elements. The following sections will discuss decoding and encoding JSON. JSON itself has a syntax consisting of comma separated key-value pairs stored as strings.

JSON Example:

{
    "key": "value",
    "key2": "value2"
}

Note JSON looks very similar to JS Objects, the difference lies in the keys not being quoted:

JS Object Example:

{
    key: "value",
    key2: "value2"
}

Keys are unique to the object they are in both JSON and Javascript, with { ... } indicating a single object.

Data Types

JSON can store a wide variety of values in the form of the following data types:

  • Strings: a quoted set of characters, like "2nd string"
  • Numbers: an integer or floating-point number, like 234.32
  • Booleans: true or false values.
  • Arrays: a set of comma-separated values of one data type between square brackets, like [1, 2, 3]
  • Objects: set of key-value pairs between curly brackets, like { "name": "Bob" }
  • Null: an empty value represented by null

The following gives an example of JSON properties with each value type:

{
    "string": "this is a string",
    
    "integer": 35,
    
    "boolean": true,
    
    "array": ["🍎","🍌","🍊","🍉","🍇","🍐"],
    
    "object": {
        "apple": "🍎",
        "orange": "🍊",
        "pear": "🍐",
        "grapes": "🍇",
        "costs": [2.99, 3.99, 4.45, 3.49]
    },
    
    "null": null
}

Note you'll often see cases where JSON objects are nested in arrays or other objects:

{
    "persons": [
        {
            "name": "Joe",
            "age": 23
        },
        {
            "name": "Priyanka",
            "age": 32
        },
        {
            "name": "Elizabeth"
            "age": 25
        }
    ]
}

JSON Schema

JSON schema is a specification detailing how to structure JSON data for validation, documentation, hyperlink navigation, and interaction control of JSON data.

The specification can be found here:
https://json-schema.org/specification.html

And is split into two parts.

Overview

JSON Schema defines the media type "application/schema+json", a JSON-based format for describing the structure of JSON data. It can be applied to a normal JSON document containing data to validate it depending on conditions set by the schema.

An instance is a JSON value interpreted according to a schema. An instance can also refer to all JSON values in a document that a schema is applied.

JSON Schemas define 6 primitive types to associate with instances:

  • null: A JSON null value
  • boolean: true or false value
  • object: unordered set of key-value pairs mapping strings to instances
  • array: ordered list of instances
  • number: base-10 decimal number
  • string: array of Unicode characters

JSON Schema vocabularies can extend the type system, for example an integer type could be defined, but the schema would classify it as a subset of number.

Keywords

Object properties that are applied to an instance are called keywords, falling under 5 categories:

  • identifiers: identify a schema through a URI or determining how a Base URI is determined.
  • assertions (validation keywords): produce booleans when applied to an instance, primary way to validate data.
  • annotations: attach data to an instance for application use
  • applicators: apply subschemas at a specific location in an instance.
  • reserved locations: reserve a place for interoperability

Common identifiers are:

  • $id: sets the URI of the current schema, this doesn't need to be a network addressable URL.
  • $schema: links a schema to another schema or specific draft URI for version control
  • $vocabulary: declares a schema as one that doesnot use the core vocabilary.

The current URI for the Core vocabulary is: https://json-schema.org/draft/2020-12/vocab/core, where $ is referred to the core.

Common assertions for any instance:

  • type: a string or array of strings containing type primitives. Checks if instance is of type.
  • enum: validates an instance if its value is equal to one of the elements in a given array.
  • const: validates an instance that matches the value given exactly (identical to enum but singular)

Assertions for numeric instances:

  • multipleOf: checks if instance is divisible % by the given number.
  • maximum: instance is less than or equal to <= the given number.
  • minimum: instance is greater than or equal to >= the given number.
  • exclusiveMaximum: instance is less than < the given number.
  • exclusiveMinimum: instance is greater than > the given number/

Assertions for strings:

  • maxLength: string is less than or equal to this length
  • minLength: string is greater than or equal to this length
  • pattern: matches string to regex pattern

Assertions for arrays:

  • maxItems: number of elements is less than or equal to this number.
  • minItems: number of elements is greater than or equal to this number.
  • uniqueItems: assigned true or false. Validates if an array has unique elements.

Assertions for objects:

  • maxProperties: number of properties <= value
  • minProperties: number of properties >= value
  • required: takes an array of strings listing property names. The object must include all properties.
  • dependentRequired: takes an object of properties with array of string values defining required properties dependent on if a key is present.

Common annotations:

  • title: titles a JSON instance. Can be pulled to be displayed on UIs.
  • description: description metadata associated with a JSON instance. Can be pulled to be displayed on UIs.
  • default: defines a default value for a JSON instance
  • readOnly: defines an instance as read only, meaning the value can't be updated.
  • writeOnly: allows instances to be defined in the future, making them blank initially. Used for defining JSON that acts as forms.

Common applicators:

  • contains: Validates an array if at least one of its elements matches a given schema.
  • properties: takes an object input. Validates if an object's value matches the following JSON sub-schema.

Example of a JSON Schema

Let's say we had JSON data based on a product catalog that we wanted to validate:

{
  "productId": 1,
  "productName": "A green door",
  "price": 12.50,
  "tags": [ "home", "green" ]
}

We can apply a schema to check if the above JSON is valid. First we define the schema for the product catalog object as a whole:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/product.schema.json",
  "title": "Product",
  "description": "A product in the catalog",
  "type": "object"
}

Identifiers: $schema and $id
Annotations: title and description
Assertions: type

Then we define how each of the properties of the catalog should look. Below we define the shape of productId, productName, price, and tags:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/product.schema.json",
  "title": "Product",
  "description": "A product from Acme's catalog",
  "type": "object",
  
  "properties": {
    "productId": {
      "description": "The unique identifier for a product",
      "type": "integer"
    },
    
    "productName": {
      "description": "Name of the product",
      "type": "string"
    },
    
    "price": {
      "description": "The price of the product",
      "type": "number",
      "exclusiveMinimum": 0
    },
    
    "tags": {
      "description": "Tags for the product",
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "uniqueItems": true
    }
  },
  
  "required": [ "productId", "productName", "price" ]
}

Let's say we also wanted to add an additional property called warehouseLocation that refers to a specific location in Latitude and Longitude. We can define a separate JSON schema defining location at https://example.com/geographical-location.schema.json:

{
  "$id": "https://example.com/geographical-location.schema.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Longitude and Latitude",
  "description": "A geographical coordinate on a planet (most commonly Earth).",
  "required": [ "latitude", "longitude" ],
  "type": "object",
  "properties": {
    "latitude": {
      "type": "number",
      "minimum": -90,
      "maximum": 90
    },
    "longitude": {
      "type": "number",
      "minimum": -180,
      "maximum": 180
    }
  }
}

Then refer to it in our original schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/product.schema.json",
  "title": "Product",
  "description": "A product from Acme's catalog",
  "type": "object",
  "properties": {
    "productId": {
      "description": "The unique identifier for a product",
      "type": "integer"
    },
    "productName": {
      "description": "Name of the product",
      "type": "string"
    },
    "price": {
      "description": "The price of the product",
      "type": "number",
      "exclusiveMinimum": 0
    },
    "tags": {
      "description": "Tags for the product",
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "uniqueItems": true
    },
    "warehouseLocation": {
      "description": "Coordinates of the warehouse where the product is located.",
      "$ref": "https://example.com/geographical-location.schema.json"
    }
  },
  "required": [ "productId", "productName", "price" ]
}

We can now use our schema to validate JSON data like the following:

  {
    "productId": 1,
    "productName": "An ice sculpture",
    "price": 12.50,
    "tags": [ "cold", "ice" ],
    "warehouseLocation": {
      "latitude": -78.75,
      "longitude": 20.4
    }
  }

JSON Decoding

Most APIs often return JSON data in a string format. Often when writing an application it is important to convert the given JSON into an object format native to the language you are working with. Most langauges have a JSON class or module that can be used to convert JSON into an object form.

In Javascript, we use JSON.parse():

// Sample JSON
const json = '{ "fruit": "apple" }'

// Parsing JSON as obj and storing in variable
let obj = JSON.parse(json);

console.log(obj.fruit) // should print "apple"

In Python we have the json.loads():

import json

# some JSON:
json_str =  '{ "fruit":"apple" }'

# parse json:
dict = json.loads(json_str)

print(dict["fruit"]) # prints "apple"

In Python we refer to objects as dictionaries(dicts).

JSON Encoding

When writing APIs, it is important to encode objects in the form of JSON. Most backend services use Object Relational Mappings (ORMs) to convert the results of Database queries into a programming language's object format for easier manipulation.

So APIs then convert the data from an object format to a JSON string to send to the client.

In JS we use json.stringify() to encode Javascript Objects into JSON:

let json = JSON.stringify({ name: "Bob", age: 45 })
console.log(json) // prints '{ "name":"Bob", "age":"45" }'

In Python we use a similar method json.dumps():

import json

dict = { "name": "Bob", "age": 45 }
str = json.dumps(obj)
print(str) # prints '{ "name": "Bob", "age": 45 }'

Applications

Similar to formats like XML and YAML, JSON offers a lightweight method of storing an transporting data.

It is often used to send data from servers, most notably through Web API protocols like:

  • REST
  • JSON-RPC
  • gRPC
  • GraphQL

It can also be used for storing configuration settings in applications, for example most package management tools will utilize json to store details on package versioning. Though YAML is also popular in these use cases as it includes features like comments, extensible data types, relational anchors, and mapping types.

JSON has certain weaknesses, for example it cannot store large data types such as images and videos. It can store hyperlinks to those resources or HTML strings to generate interfaces for those kinds resources. Yet JSON is still extremely popular due to its readability and relatively simple conversion to object formats.

With this article at OpenGenus, you must have the complete idea of Basics of JSON data format.

Sign up for FREE 3 months of Amazon Music. YOU MUST NOT MISS.