Author: Xavier Badosa / Archived under Tools
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.
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';
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 );
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;
}
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() 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() 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() 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.
}
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() displays the query and its result.
function show( $query , $result ){
foreach ($query as $key=>$value) {
echo $key.'='.$value.' ';
}
echo '==> ' . $result . "\n";
}