Using JSON Parser and Data in the C language
============================================

The JSON Parser package provides not only a JSON Parser, a JSON Generator and a
JSON Validator, but also a rich set of JSON Support Functions to assist C developers
is using JSON Data easily with the minimum of coding overhead.

This document presents basic ideas on how to use the output provided by the JSON
Parser directly with the C language and the available D-List functions. It also 
covers a wide variety of JSON data operations a developer may undertake without
using, or modifying the JSON Parser output,

Presented are some typical examples of JSON usage from other higher level coding 
environments, and how to easily achieve the same with the C language, D-List and
this package.

The actual purpose of this document is to illustrate these procedures as a mirror
to the document that describes the usage of the JSON Support Functions. Although
the JSON Support Functions provide a wide range of JSON data support, there will
be situations where a C programmer will have to navigate a JSON data hierarchy 
separately where the JSON Support Functions may not be able to find a suitable
Member Name match for example, and situations where it is much faster to navigate
directly to a known place in a JSON data hierarchy using C code and D-List. The
examples in this document are meant to assist a developer in understanding these
coding procedures and the effects these operations have on a JSON data hierarchy.

The structure of this document is identical to that of JSON-Support-Functions.txt
found in the same GUIDES directory. The sections are followed in the same order
so it is easy for a reader to both find a section in both documents and compare
coding styles required to achieve a particular goal.

As this is a lower level programming environment data types are not automatically
encoded for the callers, that will always be the responsibility of the C programmer.
As will be the normal concepts such as ensuring data is within bounds, strings are
properly terminated, etc. This is not Python after all...

Background
----------

This JSON Parser package was written to provide not only a fully functional, fast
and accurate JSON Parser for C programmers, but also to provide the JSON data in a
form that is more generally useful to C developers. Most JSON parsers write the
parsed JSON data into arrays etc, and there are numerous issues as C as a language
does not natively support unbounded or variable sized data. However the D-List 
package for C does natively provide such support with a very easy to use, and rich,
set of available functions to access, modify, add to, manipulate, manage and copy 
this variable data. The D-List package is also extremely fast & efficient and a 
great way to manipulate varied data from different sources.

All functions described in this document that start with json_xxx are part of the 
JSON Parser package, and details about there usage and arguments, can be found in
the JSON Parser documentation. All functions that start with list_xxx are part of
the D-List package.

JSON is a data format focused on inter-system and inter-language interoperability. 
If you are unfamiliar with JSON grammar or syntax, please refer to ECMA-404 and 
RFC 8259 or 
	
	http://json.org 

before trying to use the JSON Support Functions.

Throughout this JSON Parser package, all JSON Objects and JSON Arrays are accessed
and manipulated using D-List list_objects, and all JSON value items are elements
within those list_objects. The list_objects are arranged hierarchically allowing
these data structures to represent the JSON syntax exactly.

If you are unfamiliar with D-List, then please consult the reference documentation.
To find that documentation, or to learn more about list_objects, elements, and the
rich set of D-List functions; please refer to the D-List documentation, which is 
available in the D-List distribution Header Files, or a set of Doxy files that are
included in that distribution, or online at 

	http://info.fwsentry.org/dlist/index.html


Starting a new JSON Data Block from scratch.
--------------------------------------------

At the root level of a JSON data block there can be only 1 item, either a single
value, a JSON Array or a JSON Object. It you need more than a single value at the
top level, you must enclosed them in a JSON Array, or create a JSON Object.

If you do not have an existing JSON data block to read or modify, you will need to
create one first. If you have a JSON data block in a file, or one that was 
transmitted over the network, you can create the list_object representation of the
entire JSON Data by calling the function json_parse_data_block()

In all cases you will need a D-List list_object to describe whatever is at the top
level. You do this the same way the JSON Parser creates a representation of a JSON
data block. If called, the Parser will return to the caller a list_object, and one
of 3 JSON Value Types that tells the caller what that root list_object represents.
Therefore, the root list_object always has list elements (data values) in it,
they could be either:
	
	•	a single value item as a single element in that list, or
	•	a JSON array of value items, which are now a set of elements in
		that list, or
	•	a JSON Object which are a set of elements in that list that also
		have object_names filled in (as all JSON Object Members must have 
		names that are string values, even if the string is zero length).

So to pass the root list_object to another party expecting a JSON Data Block you
should pass the root list_object and a JSON value type as well, to inform the 
recipient of that JSON Data what to expect from the root list_object. In fact a 
recipient can analyse the list_object and figure out what it is easily enough, but 
passing the JSON value type cuts out needless redundant work. (See Note 1 for more 
information). This is also the format of calling the JSON Generator. 

To create a root list_object for your new JSON data hierarchy simply call
the function 

	list_object *new_root_object;
	new_root_object = json_create_new_list_object(value_type, NULL);
	
Where value_type will depend on what type of data is at the root of JSON data
tree you are building. If it is a JSON Object, you use JSON_object as the
value_type, otherwise for either a JSON Array or a single data value, use the
value_type JSON_array.

You now have a new, and empty, list_object to add elements to. The elements you
add must be consistent with the type of list_object you created. It is up to
you, the C programmer, to add the correct type of elements to the list_objects.

You can always call the JSON generator with your root list_object and see if it
will generate a JSON data text for you. If there are grammar or syntax errors
in the way you have assembled the list_objects and elements, it will throw an
error at that location in the list_object hierarchy. If there are minor errors
such as having an object_name in an Array element, a warning is written to 
stderr, and the name is just ignored. If there are structural errors, you will
be notified along with the JSON generation failure.

You could always use the D-List function list_create() to create a list_object
but the JSON support function json_create_new_list_object() also sets the list
up and attaches the correct default functions. It is best to use this function
instead, it is how the JSON Parser sets up all the list_objects it creates.


Adding New Elements to the list_object
--------------------------------------

All elements in every list_object throughout the JSON data hierarchy, be they at
the root level or below, must have a JSON value type recorded in them. This is so
everyone who touches the element will know exactly what the value type is, and 
cannot make a mistake of loading an integer into a pointer, or similar mistakes.

Continuing the previous example above with a new JSON data hierarchy, let's 
assume the new list_object is a JSON Object.

Adding a JSON Object Member <"member name" : value>
---------------------------------------------------

To add a new JSON Object Member to this JSON Object list_object, the only actions
required are to fill in a template of the element, and attach it to the list_object.
(see Note 2)

For this example let's assume you wish to add a Member:value pair of "Hayao" : 72
	char new_name[] = "Hayao";				/* make sure this is somewhere safe, not the stack */
	list_object *root_object;					(see Note 3)
	json_element_t new_element;
	
	new_element.value_type = JSON_integer;
	new_element.object_name = new_name;				/* a simple example, but this is not safe */
	new_element.free_string_ptr = FALSE; 			/* See next snippet */
	new_element.value.integer = 72;
	list_append(root_object, &new_element);			/* add new Member to JSON Object */
		
after this the root_object will have 1 element in it, and if you called the JSON 
Generator with this root list_list at this point, the generated JSON representation
would be

	{ "Hayao": 72 }

Now the above example was overly simple for demonstration purposes. There is the
real issue of where to store the strings associated with any list element. The 
elements themselves store all values except strings of which only the pointer to
the string is stored (as they are of fixed length). The design of this JSON Package
was meant to be small and simple, so having fixed length small elements made the
most sense. 

String values can be stored wherever the C Programmer wishes. If they are in some
fixed safe storage, then they can be added to elements as pointers without issue.
If they are not, such as in the pseudo example above, then it is recommended that
string values be put in storage created by malloc(). The issue with that, from the
developers point of view, is keeping track of all the memory chucks that have been
allocated, for later disposal (i am assuming you are all good programmers who 
garbage collect all your allocated memory before exiting your code). So to solve
that problem and make the JSON code clean, every list_object that is created in a
JSON data hierarchy has a remove function attached to it. When an element is being
erased it will release any resources the element is using. By setting the element
field free_string_ptr to TRUE for an element, any strings the element uses will
be automatically freed when the element is removed. This includes value strings 
and in this case object_name strings. So to redo the above example in a slightly
more proficient way:

	#define the_name		"Miyazaki"
	#define the_job			"Director"
	list_object *root_object;
	json_element_t new_element;
	char *name_ptr, *job_ptr;
	
	name_ptr = malloc(sizeof(the_name) + 1);
	job_ptr = malloc(sizeof(the_job) + 1);
	strcpy (name_ptr, the_name);
	strcpy (job_ptr, the_job);
	
	new_element.value_type = JSON_string;
	new_element.object_name = name_ptr;				/* now this is a safe way */
	new_element.free_string_ptr = TRUE;
	new_element.value.string = job_ptr;
	list_append(root_object, &new_element);			/* add new Member to JSON Object */

So now the root list_object has 2 elements in it, and if you called the JSON 
Generator with this root list_list at this point, the generated JSON representation
would be

	{ 
		"Hayao": 72,
		"Miyazaki": "Director"
	}

of which the second element will also auto-remove the allocated strings "Miyazaki"
and "Director", where for the first element, you will have to free that storage
prior to calling list_erase(root_list);

You can achieve clean code with no memory leaks in many ways, but this is just
one tool to make life easier. You are free to use it, or not.

In the last example we added a Object Member with a string value. The process is
same for any of the other value types as well, set the correct value_type, add the
specific value to the value.xxxx field of the element, and you are done.

Adding a JSON Array value
-------------------------

Building on the previous example if you wish to add an element to a JSON Object
that has an Array value, here is an example. From now on the examples will be 
kept simple and ignore the malloc() etc. The assumption is the strings etc are
in safe storage somewhere.

	list_object *array_object;
	json_element_t new_element;
	char array_name[] = "films";
	json_integer_t dates[] = { 1988, 1992, 1998, 2002, 2008, 2014 };
	int i = 0;

	array_object = json_create_new_list_object(JSON_array, NULL);
	new_element.value_type = JSON_array;
	new_element.object_name = array_name;
	new_element.free_string_ptr = TRUE;
	new_element.value.object = array_object;
	list_append(root_object, &new_element);			/* add new Member to JSON Object 
														that points to Array list_object */
	while (i < 6) {
		memset(&new_element, 0x00, sizeof(json_element_t));
		new_element.value_type = JSON_integer;
		new_element.value.integer = dates[i++];				/* no need for .free_string_ptr no strings to release */
		list_append(array_object, &new_element);			/* add new Member to JSON Array */
	}

So now the root list_object has 3 elements in it, and if you called the JSON 
Generator with this root list_list at this point, the generated JSON representation
would be

	{ 
		"Hayao": 72,
		"Miyazaki": "Director",
		"films": [ 1988, 1992, 1998, 2002, 2008, 2014 ]
	}

So now you notice that the list of values in the Array is not ordered, so
let's sort it.

	list_fast_sort(array_object, LIST_ASCENDING, ENTIRE_LIST);

Adding a JSON Object Value
--------------------------

The same applies if you want to add an element which starts a new JSON Object,
the code is basically the same, except the new Elements being Object Members must
have names.

	list_object *new_json_object;
	list_object *array_object;
	json_element_t new_element;
	char new_object_name[] = "museums";
	char museums_to_add[][] = { "Louvre", "Tate", "MOMA", "Getty", "" };
	char location[][] = { "Paris", "London", "New York", "Santa Monica","" };
	int i = 0;

	new_json_object = json_create_new_list_object(JSON_object, NULL);
	new_element.value_type = JSON_object;
	new_element.value.object = new_json_object;
	list_prepend(array_object, &new_element);			/* add new value to front of JSON Array 
															that points to new Object list_object */
	while (museums_to_add[i][0] != '\0') {
		memset(&new_element, 0x00, sizeof(json_element_t));
		new_element.value_type = JSON_string;
		new_element.object_name = museums_to_add[i];
		new_element.value.string = location[i++];
		new_element.free_string_ptr = TRUE;
		list_append(new_json_object, &new_element);			/* add new Member to new JSON Object */
	}

So now the root list_object still has 3 elements in it, and if you called the JSON 
Generator with this root object_list at this point, the generated JSON representation
would be

	{ 
		"Hayao": 72,
		"Miyazaki": "Director",
		"films": [ {
						"Louvre": "Paris", 
						"Tate": "London", 
						"MOMA": "New York", 
						"Getty": "Santa Monica"
					},
					1988, 1992, 1998, 2002, 2008, 2014 ]
	}

It should be noted the the JSON Generator will generate JSON text from any valid 
JSON data hierarchy. So for example to test a piece of data without rendering the
entire block, you can call it with a sample from above:

	char *output_buffer;
	ret = json_generate_data_block(new_json_object, JSON_object, &output_buffer);

and you would get this output instead, although the entire JSON data block is still
intact

	{
		"Louvre": "Paris", 
		"Tate": "London", 
		"MOMA": "New York", 
		"Getty": "Santa Monica"
	}

Moving elements between lists
-----------------------------

Let's say you discovered you put the elements in the wrong place. And they are
supposed to be in a separate Object Member on the root level. You will have 
noticed that the string "Museums" was not used in the above snippet, that was
the mistake that was discovered. We can easily rectify this:

	list_object *top_json_object;
	list_object *new_json_object;		/* still has the JSON Obj ptr */
	list_object *array_object;			/* still the same */
	list_object *root_object;
	json_element_t new_element;
	char new_object_name[] = "museums";

	top_json_object = json_create_new_list_object(JSON_object, NULL);
	new_element.value_type = JSON_object;
	new_element.object_name = new_object_name;			/* this is going in an Object */
	new_element.free_string_ptr = TRUE;
	new_element.value.object = top_json_object;
	list_append(root_object, &new_element);
	
	list_transfer(new_json_object, top_json_object);	/* move all the elements */
	list_erase(new_json_object);						/* remove the incorrect list_object */
	new_json_object = NULL;								
	list_delete_index(array_object, 0);					/* remove the first Array value */

So now the root list_object still has 4 elements in it, and if you called the JSON 
Generator with this root object_list at this point, the generated JSON representation
would be

	{ 
		"Hayao": 72,
		"Miyazaki": "Director",
		"films": [ 1988, 1992, 1998, 2002, 2008, 2014 ],
		"museums": {
						"Louvre": "Paris", 
						"Tate": "London", 
						"MOMA": "New York", 
						"Getty": "Santa Monica"
					}
	}











also if it is 
not a value, but a nested JSON Array or JSON Object instead.
You can do this one of 2 different ways. 

You can create a list_object that 

The JSON Parser will return 

If this s a root level JSON Object it will have no member name, just an opening '{'
so with this package you use list_create(name, ..) to create the root object. This 
would also be true if


































NOTES
=====

(1)		As an aside, the process to know what a root list_object is if it passed to
		you with no JSON value type attached, is:
			•	Does the first element contain an non-null object_name string ?
				YES, then the list_object must be describing a JSON Object at 
				the top of the JSON Data tree.
			*	Is there only 1 element ? AND is that element a data value item ?
				(not a JSON Array or JSON Object). YES, then this is a JSON Data
				Block (or an Array) that contains only 1 value item.
			•	Then the list_object must be describing a JSON Array at the top
				of the JSON Data tree.

(2)		JSON Object Members are also known as a key:value pair in various other 
		environments, such as JavaScript land. Throughout this JSON Package and 
		this document in particular, we try and keep the terminology consistent 
		with the terminology used in RFC 8529 and ECMA-404 to avoid confusion.

(3)		These code snippets are not real-world, for example to add a character
		array to an element, you must also leave the character array in a memory
		location will not be deallocated while the list_object is still being used
		(i.e. prior to calling list_erase() ) this code snipper would fail as soon
		as the pretend function called return, the character array in this example
		is on the stack.

		