read


Previous: Build
Next: Write

Read a json file


Previous: Build example
Next: Write a file

A json file is like a xml, but in a simplest way. It is in the minimum constituated of:
{}
This is the simplest json code.
for example we will use the next json file :
{
	"element1":25622.53,
	"element2":"a string...",
	"is active":false,
	"NULL element":null,
	"exampleObject":{
		"a string":"my super example of string",
		"a null element":null,
		"an array element":[
			12, 25, 65, 654
		],
		"a boolean Element":true,
		"a simple sumber"=156156.343,
		"an other object":{
			"plop": 1,
			"plop2": 2
		}
	},
	"exampleArray":[
		12,
		25,
		65,
		654,
		{
			"plup": true,
			"plup2": false
		},
		true,
		null,
		[ 22, 23, 24, 25]
	}
}


Open the file


The first step to open a file is to create the json document:
#include <ejson/ejson.h>

int main() {
	// declare document
	ejson::Document doc;
	...
}

Load a stored file


It is important to remember that the input file is manage by etk, then the naming form is describe by the class: etk::FSNode
	// read file
	if (doc.load("DATA:example.json") == false) {
		APPL_ERROR("An error occured when reading the file...");
		// TODO : STANDARDIZE ERROR....
		return -1;
	}

Load a file stored in memory


This step is easyest has a reading in a file.
In the first step, declare a string containing the json description:
	std:string myJson = "{ \"element1\":25622.53, \"element2\":\"a string...\" }";

Now we just need to load the string:
	if (doc.parse(myJson) == false) {
		APPL_ERROR("An error occured when parsing the string");
		return -1;
	}

it could be interesting to add some \n in the string to find some error in the json string

Access on the data


now we have the data stored in the doc instance, it could be interesting to access on it.
Despite of XML interface that is not designed to be keep in memory but just parsed and drop, the json element is many time use as a simple interface to acces on the data.
This is the reason for this json interfce is designed for simple acces and use.

The simple way


Read a number value in the doc:
	double myValue = doc.getNumberValue("element1", 49);
	APPL_INFO("Get the element value:" << myValue);
Note that we had a return value, in case of the element is not present or in the wrong form.
We have the same interface for boolean, string and number: These interface methode are availlable for ejson::Document, ejson::Object. The similar interface are availlable on ejson:Array: It could be interesting to remember that the maain node of a json file in an object, this is the reason that ejson::Document herited of ejson::Object.

The generic way


The classical way to read a json file is to parse it like a xml:

Object

We are now reading all node in an object:
	ejson::Object* obj = doc.getObject("exampleObject");
	// note that the obj is NULL if it not an "Object"
	if (obj == NULL) {
		APPL_ERROR("Can not get the object 'exampleObject' in the json file");
		return -1;
	}
Note at this point we can parse an object in 2 way:
1: The fastest but not the best:
	for (size_t iii=0; iii < obj->size(); ++iii) {
		std::string key = obj->getKey(iii);
		ejson::Value* val = obj[iii];
		// note that error can appear, then check result...
		if (val == NULL) {
			APPL_ERROR("Can not read the object id=" << iii);
			continue;
		}
		switch(val->getType()) {
			case typeArray: {
				ejson::Array* myArray = val->toArray();
				APPL_INFO("Find an Array @" << key);
				} break;
			case typeString: {
				ejson::String* myString = val->toString();
				APPL_INFO("Find a String @" << key << " value='" << myString->get() << "'");
				} break;
			case typeNumber: {
				ejson::Number* myNumber = val->toNumber();
				APPL_INFO("Find a Number @" << key << " value='" << myNumber->get() << "'");
				} break;
			case typeBoolean: {
				ejson::Boolean* myBoolean = val->toBoolean();
				APPL_INFO("Find a Boolean @" << key << " value='" << myBoolean->get() << "'");
				} break;
			case typeNull:
				APPL_INFO("Find a null @" << key);
				break;
			case typeObject: {
				ejson::Object* myObject = val->toObject();
				APPL_INFO("Find an Object @" << key);
				} break;
		}
	}

2: A more generic way to acces on the elemnts:
	stk::vector<std::string> keys = obj->getKeys();
	for (auto key in keys) {
		ejson::Value* val = obj[key];
		// note that error can appear, then check result...
		if (val == NULL) {
			APPL_ERROR("Can not read the object key=" << key);
			continue;
		}
		switch(val->getType()) {
			case typeArray: {
				ejson::Array* myArray = val->toArray();
				APPL_INFO("Find an Array @" << key);
				} break;
			case typeString: {
				ejson::String* myString = val->toString();
				APPL_INFO("Find a String @" << key << " value='" << myString->get() << "'");
				} break;
			case typeNumber: {
				ejson::Number* myNumber = val->toNumber();
				APPL_INFO("Find a Number @" << key << " value='" << myNumber->get() << "'");
				} break;
			case typeBoolean: {
				ejson::Boolean* myBoolean = val->toBoolean();
				APPL_INFO("Find a Boolean @" << key << " value='" << myBoolean->get() << "'");
				} break;
			case typeNull:
				APPL_INFO("Find a null @" << key);
				break;
			case typeObject: {
				ejson::Object* myObject = val->toObject();
				APPL_INFO("Find an Object @" << key);
				} break;
		}
	}

Array


We are now reading all node in an Array:
	ejson::Array* obj = doc.getArray("exampleArray");
	// note that the obj is NULL if it not an "Array"
	if (obj == NULL) {
		APPL_ERROR("Can not get the array 'exampleArray' in the json file");
		return -1;
	}

Note for an array we have only one methode to parse the data :
	for (size_t iii=0; iii < obj->size(); ++iii) {
		ejson::Value* val = obj[iii];
		// or ejson::Value* val = obj->get(iii);
		// note that error can appear, then check result...
		if (val == NULL) {
			APPL_ERROR("Can not read the object id=" << iii);
			continue;
		}
		switch(val->getType()) {
			case typeArray: {
				ejson::Array* myArray = val->toArray();
				APPL_INFO("Find an Array @" << key);
				} break;
			case typeString: {
				ejson::String* myString = val->toString();
				APPL_INFO("Find a String @" << key << " value='" << myString->get() << "'");
				} break;
			case typeNumber: {
				ejson::Number* myNumber = val->toNumber();
				APPL_INFO("Find a Number @" << key << " value='" << myNumber->get() << "'");
				} break;
			case typeBoolean: {
				ejson::Boolean* myBoolean = val->toBoolean();
				APPL_INFO("Find a Boolean @" << key << " value='" << myBoolean->get() << "'");
				} break;
			case typeNull:
				APPL_INFO("Find a null @" << key);
				break;
			case typeObject: {
				ejson::Object* myObject = val->toObject();
				APPL_INFO("Find an Object @" << key);
				} break;
		}
	}

It is important to note that many time the user know what type will appear in a list or in an object , then you can directly use: These fuction automatly cast the resut in the good form (if it is the real one)