The JSON-stat format is a simple lightweight JSON format for data dissemination. It is based in a cube model that arises from the evidence that the most common form of data dissemination is the tabular form. In this cube model, datasets are organized in dimensions. Dimensions are organized in categories.

Data dissemination is not the business of a few anymore. Even though the JSON-stat format can be the perfect companion for the open data initiatives of National Statistical Offices, it is suitable for all kinds of data disseminators because it has been designed with simplicity in mind.

Apart from reading the documentation, you can also learn the format checking the sample files at your disposal. Besides these madeup files, the Statistics Norway API offers more than a hundred updated JSON-stat responses.

You can browse the content of a JSON-stat response with the JSON-stat Format Viewer.

JSON-stat Format Documentation

dataset

object free word required

ParentsNone
Childrenvalue, status, dimension, label, updated, source

A JSON-stat response can contain one or more datasets (or tables, or cubes). They are identified by an ID (a string). Multiple datasets responses allow a provider to disseminate information with few common dimensions in a single response.

{
   "cpi*prod*201207" : {
      
   },
   "pob*counties*2012" : {
      
   }
}

The dataset ID can be any standardized string used by the provider and should be a parameter in the request or be computable from the request parameters. If a provider does not plan to support responses with multiple datasets, using specific IDs could be unnecessary: any fixed word would do the job. In such a case, the recommended ID is dataset.

{
   "dataset" : {
      
   }
}

value

array object reserved word required

Parentsdataset
ChildrenNone

It contains the data sorted according to the dataset dimensions. It usually takes the form of an array where missing values are expressed as nulls.

{
   "dataset" : {
      "value" : [105.3, 104.3, null, 177.2, ]
   }
}

When too many cube cells are empty (sparse cube), the value array is populated with nulls.

{
   "dataset" : {
      "value" : [1.3587, null, null, null, null, null, null, null, null,
                null, null, null, null, null, null, null, null, null, 1.5849],
      
   }
}

To avoid this, the value property can take the form of an object.

{
   "dataset" : {
      "value" : { "0": 1.3587, "18": 1.5849 },
      
   }
}

Value order follows the “What does not change, first” criterion. According to this criterion, values are ordered by combination of category dimensions keeping fixed the first categories of the first dimensions and iterating through the categories of the last dimension in the id array (and so forth).

For example, if we have three dimensions (A, B and C) with 3, 2 and 4 categories respectively, the values should ordered iterating first by the 4 categories of C, then by the 2 categories of B and finally by the 3 categories of A:

A1B1C1   A1B1C2   A1B1C3   A1B1C4
A1B2C1   A1B2C2   A1B2C3   A1B2C4

A2B1C1   A2B1C2   A2B1C3   A1B1C4
A2B2C1   A2B2C2   A2B2C3   A2B2C4

A3B1C1   A3B1C2   A3B1C3   A3B1C4
A3B2C1   A3B2C2   A3B2C3   A3B2C4

The order.json file is provided as a JSON-stat example of value and dimension sorting.

status

array object string reserved word optional

Parentsdataset
ChildrenNone

It contains metadata at the observation level. When it takes an array form of the same size of value, it assigns a status to each data by position.

{
   "dataset" : {
      "value" : [100, null, 102, 103, 104],
      "status" : ["a", "m", "a", "a", "p"],
      
   }
}

To assign the same status to all data, an array of size 1 can be used.

{
   "dataset" : {
      "value" : [100, 99, 102, 103, 104],
      "status" : ["e"],
      
   }
}

For the same purpose, a string can be used (this is the recommended way to assign the same status to all data).

{
   "dataset" : {
      "value" : [100, 99, 102, 103, 104],
      "status" : "e",
      
   }
}

An object can also be used to provide status information for specific cells.

{
   "dataset" : {
      "value" : [100, null, 102, 103, 104],
      "status" : { "1" : "m" },
      
   }
}

Currently, “status” does not have a standard meaning nor a standard vocabulary. These are, for the moment, up to the provider. It can be used to optionally include any metadata information at the observation level, not only what is regularly known as “status”. If the vocubulary does not adhere to a standard, there is no way yet to assign meaning to the status codes in the same response.

dimension

object reserved word required

Parentsdataset
Childrenid, size, role, dimension ID

JSON-stat follows a cube model: the values are organized in cells, and a cell is the intersection of various dimensions. The dimension property contains information about the dimensions of the dataset.

{
   "dataset" : {
      "value" : [4729, 4832, 9561],
      "dimension" : {
         
      }
   }
}

id

array reserved word required

Parentsdimension
ChildrenNone

It contains an ordered list of dimension IDs (strings).

"dimension" : {
   "id" : ["metric", "time", "geo", "sex"], 
   
}

Dimension IDs can be any string and have no special meaning in JSON-stat. Use role to assign a particular meaning to them.

dimension must have an object with the same name as every dimension in this array (see dimension ID).

size

array reserved word required

Parentsdimension
ChildrenNone

It contains the number (integer) of categories (possible values) of each dimension. It has the same number of elements and in the same order as id.

"dimension" : {
   "id" : ["metric", "time", "geo", "sex"], 
   "size" : [1, 1, 1, 3], 
   
}

In this website, dimensions of size 1 (single category dimensions) are called constant dimensions. Their position in the id and size arrays is irrelevant because they do not affect the values order.

role

object reserved word optional

Parentsdimension
Childrentime, geo and metric

It can be used to assign special roles to dimensions. At this moment, possible roles are: time, geo and metric. A role can be shared by several dimensions.

"dimension" : {
   "id" : ["concept", "arrivaldate", "departuredate", "origin", "destination"],
   "size" : [1, 24, 24, 10, 10],
   "role": {
      "time": ["arrivaldate", "departuredate"],
      "geo": ["origin", "destination"],
      "metric": ["concept"]
   },
   
}

time

array reserved word optional

Parentsrole
ChildrenNone

It can be used to assign a time role (when?) to one or more dimensions. It takes the form of an array of dimension IDs in which order does not have a special meaning.

"role": {
   "time": ["arrivaldate", "departuredate"]
}

geo

array reserved word optional

Parentsrole
ChildrenNone

It can be used to assign a spatial role (where?) to one or more dimensions. It takes the form of an array of dimension IDs in which order does not have a special meaning.

"role": {
   "geo": ["origin", "destination"]
}

metric

array reserved word optional

Parentsrole
ChildrenNone

It can be used to assign a metric role (what are we counting?) to one or more dimensions. It takes the form of an array of dimension IDs in which order does not have a special meaning.

"role": {
   "metric": ["concept"]
}

dimension ID

object free word required

Parentsdimension
Childrencategory, label

It is used to describe a particular dimension. The name of this object must be one of the strings in the id array. There must be one and only one dimension ID object for every dimension in the id array.

"dimension" : {
   "id" : ["metric", "time", "geo", "sex"],
   "size" : [1, 1, 1, 3],
   "metric" : {  }, 
   "time" : {  }, 
   "geo" : {  }, 
   "sex" : {  },
   
}

category

object reserved word required

Parentsdimension ID
Childrenindex, label, child, coordinates, unit

It is used to describe the possible values of a dimension.

"sex" : {
   "category" : {  }
}

index

object array reserved word optional

Parentscategory
ChildrenNone

It is used to order the possible values (categories) of a dimension. The order of the categories and the order of the dimensions themselves determine the order of the data in the value array. While the dimensions’ order has only this functional role (and therefore any order chosen by the provider is valid), the categories’ order has also a presentation role: it is assumed that the categories are sorted in a meaningful order and that the consumer can rely on it when displaying the information. For example, categories in dimensions with a time role are assumed to be in chronological order.

To provide the category IDs and their order, an array can be used.

"sex" : {
   "category" : {
      "index" : ["M", "F", "T"]
   }
}

For efficiency reasons (see Arrays vs. Objects), an object that attaches a position to every ID can also be used (this is currently the recommended format).

"sex" : {
   "category" : {
      "index" : {
         "M" : 0,
         "F" : 1,
         "T" : 2
      }
   }
}

index is required unless the dimension is a constant dimension (dimension with a single category). When a dimension has only one category, the index property is indeed unnecessary. In the case that a category index is not provided, a category label must be included.

label

string object reserved word optional

Parentsdataset, dimension ID, category
ChildrenNone

It is used to assign a very short (one line) descriptive text to IDs at different levels of the response tree. It is language-dependent.

When it is a child of dataset or dimension ID, it is a string.

{
   "dataset" : {
      "label" : "Tuvalu population by sex in the 2002 Census",
      "dimension" : {
         "sex" : {
            "label" : "Sex",
            
         },
         
      }
   }
}

When it is a child of category, it is an object where the keys are the category IDs and the values are the labels.

"sex" : {
   "label" : "Sex",
   "category" : {
      "index" : {
         "M" : 0,
         "F" : 1,
         "T" : 2
      },
      "label" : {
         "M" : "Men",
         "F" : "Women",
         "T" : "Total"
      }
   }
}

Sometimes, the dimension categories have a hierarchical relationship. This relationship can be expressed using the child property.

When no category labels are provided, the recommended behavior for a JSON-stat client is to use the IDs (as they appear in index) as labels. In this case, IDs should be chosen wisely.

"year" : {
   "category" : {
      "index" : {
         "2003" : 0,
         "2004" : 1,
         "2005" : 2,
         "2006" : 3,
         "2007" : 4,
         "2008" : 5,
         "2009" : 6,
         "2010" : 7,
         "2011" : 8,
         "2012" : 9,
         "2013" : 10,
         "2014" : 11
      }
   ,
      "label" : {
         "2003" : "2003",
         "2004" : "2004",
         "2005" : "2005",
         "2006" : "2006",
         "2007" : "2007",
         "2008" : "2008",
         "2009" : "2009",
         "2010" : "2010",
         "2011" : "2011",
         "2012" : "2012",
         "2013" : "2013",
         "2014" : "2014"
      }
   }
}

When a dimension is a constant dimension and no category index is provided for it, category labels are required.

"metric" : {
   "category" : {
      "index" : {
         "pop" : 0
      },
      "label" : {
         "pop" : "Population"
      }
   }
   
}

Of course, if the dimension is constant and the label is not important, you can choose to remove the category label instead of the category index.

"year" : {
   "category" : {
      "index" : {
         "2013" : 0
      },
      "label" : {
         "2013" : "2013"
      }
   }
   
}

child

object reserved word optional

Parentscategory
ChildrenNone

It is used to describe the hierarchical relationship between different categories. It takes the form of an object where the key is the ID of the parent category and the value is an array of the IDs of the child categories. It is also a way of exposing a certain category as a total.

"actstatus": {
   "label":"Activity status",
   "category": {
      "index": {
         "A" : 0,
         "E" : 1,
         "U" : 2,
         "I" : 3,
         "T" : 4
      },
      "label": {
         "A" : "Active population",
         "E" : "Employment",
         "U" : "Unemployment",
         "I" : "Inactive population"
         "T" : "Population 15 years old and over"
      },
      "child": {
         "A" : ["E", "U"],
         "T" : ["A", "I"]
      }
   }
}

When there are several hierarchy levels, like in the previous example, child must reference only the direct descendants. For example, the oecd-canada.json sample file includes a total (OECD) and a subtotal (EU15): the 15 countries in EU15 are not directly referenced as OECD countries.

"child" : {
   "EU15" : [
      "AT", 
      "BE", 
      "DE", 
      "DK", 
      "ES", 
      "FI", 
      "FR", 
      "GR", 
      "IE", 
      "IT", 
      "LU", 
      "NL", 
      "PT", 
      "SE", 
      "UK"
   ],
   "OECD" : [ 
      "EU15", 
      "AU", 
      "CA", 
      "CL", 
      "CZ", 
      "DK", 
      "EE", 
      "HU", 
      "IS", 
      "IL", 
      "JP", 
      "KR", 
      "MX", 
      "NO", 
      "NZ", 
      "PL", 
      "SK", 
      "SI", 
      "CH", 
      "TR", 
      "US"
   ]
}

As an example, see hierarchy.json.

coordinates

object reserved word optional

Parentscategory
ChildrenNone

It can be used to assign longitude/latitude geographic coordinates to the categories of a dimension with a geo role. It takes the form of an object where keys are category IDs and values are an array of two numbers (longitude, latitude).

"category" : {
   "label" : {
      "ISO-3166-2:TV" : "Tuvalu"
   },
   "coordinates" : {
      "ISO-3166-2:TV" : [179.1995, -8.5199]
   }
}

The goal of JSON-stat is not to provide rich geographical information. To that purpose, use GeoJSON or TopoJSON and match your maps areas in those formats with statistical data (in JSON-stat) encoding your geographical categories with common IDs.

unit

object reserved word optional

Parentscategory
ChildrenCategory IDs

It can be used to assign unit of measure metadata to the categories of a dimension with a metric role.

"role": {
   "metric": ["concept"]
}

It takes the form of an object where every dimension category is a key and the value is an object. The properties of this object are not closed.

"concept" : {
   "category" : {
      "label" : {
         "pop" : "Population"
      },
      "unit" : {
         "pop" : {  }
      }
   }
}

Based on current standards and practices, possible properties of this object could be:

  • label: It could be a language-dependent text to display with the values (like “millions of dollars”).
  • type: This property should probably help deriving new data from the data. It should probably help answering questions like: does it make sense to add two different cell values? Some possible values of this property could be count or ratio. Some might also consider as possible values things like currency, mass, length, time, etc.
  • base: It is the base unit (person, gram, euro, etc.).
  • multiplier: It is the unit multiplier. It should help comparing data with the same base unit but different multiplier. If a decimal system is used, it can be expressed as powers of 10 (0=1, 1=10, -1=0.1, etc.).
  • symbol: A possible symbol to add to the data when it is displayed (for example, €, $ or %). It could be language-dependent.
  • position: The place where the symbol should be written (before or after the data). Possible values could be start and end. It is language-dependent.
  • adjustment: A code to express the time series adjustment (for example, seasonally adjusted or adjusted by working days) or indices adjustment (for example, chain-linked indices).
  • decimals: The number of decimals.

updated

string reserved word optional

Parentsdataset
ChildrenNone

It contains the update time of the dataset. It is a string representing a date in an ISO 8601 format recognized by the Javascript Date.parse method.

{
   "dataset" : {
      "updated" : "2012-01-22T12:30:02Z",
      
   }
}

source

string reserved word optional

Parentsdataset
ChildrenNone

It contains a language-dependent short text describing the source of the dataset.

{
   "dataset" : {
      "source" : "Economic Outlook No 92 - December 2012 - OECD Annual Projections",
      
   }
}