PHP Sample Code

Author: / Archived under Tools

View raw code

The JSON-stat format stores multidimensional data (a cube) as a unidimensional array using the row-major order method. This sample code illustrates how you can get the value of a particular cube cell (see the getValue() function). For this, it’s necessary to translate multidimensional indices (categories) into a unidimensional one (value).

This code has been written with clarity in mind, not efficiency.

See this code running on PhpFiddle.

Main

External variables

Example 1: Unemployment rate in the US in 2010 according to the sample OECD dataset (oecd.json).

Result: 9.627692959

$query=array(
  'concept'=>'UNR',
  'area'=>'US',
  'year'=>'2010'
);

$url='http://json-stat.org/samples/oecd.json';

Example 2: Value in cell with dimension A=‘1’, dimension B=‘2’ and dimension C=‘4’ in the sample “order” dataset (order.json).

Result: 'A1B2C4'

$query=array(
  'A'=>'1', //1..3
  'B'=>'2', //1..2
  'C'=>'4' //1..4
);

$url='http://json-stat.org/samples/order.json';

Example 3: 0-4 years old population in 1900 according to Statistics Norway 65195 dataset.

Result: 286900

$query=array(
	'Alder'=>'F00-04',
	'Kjonn'=>'0',
	'Tid'=>'1900',
	'ContentsCode'=>'Personer'
);

$url='http://data.ssb.no/api/v0/dataset/65195.json';

Program

This program returns some data value by categories’ IDs (expressed as an assoc array: $query) from a remote dataset (expressed as a URL: $url).

//Read: Get JSON-stat as PHP object from URL
$jsonstat=JSONstat( $url );

//Parse: Get value from $jsonstat and $query
$value=getValue( $jsonstat , $query );

//Write: Display query and result
show( $query , $value );

Core function

getValue()

getValue() converts a dimension/category assoc array into a data value in three steps.

Input example: array('concept'=>'UNR','area'=>'US','year'=>'2010')

Output example: 9.627692959

function getValue( $jsonstat , $query ){

  //1. array('concept'=>'UNR','area'=>'US','year'=>'2010') ==> array(0, 33, 7)
  $indices=getDimIndices( $jsonstat , $query );

  //2. array(0, 33, 7) ==> 403
  $index=getValueIndex( $jsonstat , $indices );

  //3. 403 ==> 9.627692959
  $value=getValueByIndex( $jsonstat , $index );

  return $value;
}

Helper functions

getDimIndices()

getDimIndices() converts a dimension/category assoc array into an array of dimensions’ indices.

Input example: array('concept'=>'UNR','area'=>'US','year'=>'2010')

Output example: array(0, 33, 7)

function getDimIndices( $jsonstat , $query ){
  $dim=$jsonstat->dimension;
  //JSON-stat 2.0-ready
  $ids=( isset( $jsonstat->id ) ) ? $jsonstat->id : $dim->id;
  $ndims=count( $ids );

  $arr=array();
  for( $i=0; $i<$ndims ; $i++ ){
    $arr[$i]=getDimIndex( $dim , $ids[$i] , $query[$ids[$i]] );
  }

  return $arr;
}

getValueIndex()

getValueIndex() converts an array of dimensions’ indices into a numeric value index.

Input example: array(0, 33, 7)

Output example: 403

function getValueIndex( $jsonstat , $indices ){
  //JSON-stat 2.0-ready
  $size=( isset( $jsonstat->size ) ) ? $jsonstat->size : $jsonstat->dimension->size;
  $ndims=count( $size );
  $num=0;
  $mult=1;

  for( $i=0; $i<$ndims; $i++ ){
    $mult*=( $i>0 ) ? $size[$ndims-$i] : 1;
    $num+=$mult*$indices[$ndims-$i-1];
  }
  return $num;
}

getDimIndex()

getDimIndex() converts a dimension ID string and a category ID string into the numeric index of that category in that dimension.

Input example: "area", "US"

Output example: 33

function getDimIndex( $dim , $name , $value ){
  //In single category dimensions, "index" is optional
  if( !isset( $dim->$name->category->index ) ){
    return 0;
  }

  $ndx=$dim->$name->category->index;

  //"index" can be an object or an array
  if( is_object( $ndx ) ){ //Object
    return $ndx->$value;
  }else{ //Array
    return array_search( $value , $ndx , TRUE );
  }
}

getValueByIndex()

getValueByIndex() converts a numeric value index into its data value.

Input example: 403

Output example: 9.627692959

function getValueByIndex( $val , $index ){
  //"value" can be an array or an object (sparse cube)
  return
    is_array( $val ) ?
    $val[$index] :
    $val->$index
  ;
  //This check is avoidable if JSON is read into a
  //PHP assoc array (instead of an object). This is
  //not recommended, though, as the distinction
  //between assoc array and sequential array in
  //getDimIndex() would be less safe.
}

Utility functions

JSONstat()

JSONstat() connects to a URL and, if the response is valid JSON-stat, returns a PHP object.

function JSONstat( $url ){
  $resp=file_get_contents( $url );
  if( $resp===FALSE ){
    exit( 'Error: the contents of ' . $url . ' could not be retrieved.' . "\n" );
  }

  //Convert into object (instead of assoc array: safer to detect if category index is array or not)
  $jsonstat=json_decode( $resp );
  if( $jsonstat===NULL ){
    exit( 'Error: response was not valid JSON.' . "\n" );
  }

  //If no "class", "bundle" response:
  //use the first dataset available
  //(assuming single dataset bundle response)
  //[Of course, it'd be better to add an argument
  //to the function to pass a dataset ID if
  //bundle responses must be properly supported.]
  if( !isset( $jsonstat->class ) ){
    $dsname=each( $jsonstat )['key'];
    $jsonstat=$jsonstat->$dsname;
  }else{ //Verify it's a "dataset" response
    if( $jsonstat->class!='dataset' ){
      exit( 'Error: response was not a JSON-stat bundle or dataset response.' . "\n" );
    }
  }

  //Program requires "value" and "dimension" properties
  if( !isset( $jsonstat->value ) || !isset( $jsonstat->dimension ) ){
    exit( 'Error: response is not valid JSON-stat or does not contain required information.' . "\n" );
  }

  return $jsonstat;
}

show()

show() displays the query and its result.

function show( $query , $result ){
  foreach ($query as $key=>$value) {
    echo $key.'='.$value.' ';
  }
  echo '==> ' . $result . "\n";
}