blob: ec30b0c253df723b5f6d35e4c02a73305842ec60 [file] [log] [blame]
.** vim: sw=4 ts=4 et :
.if false
==================================================================================
Copyright (c) 2020 Nokia
Copyright (c) 2020 AT&T Intellectual Property.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================================
.fi
.if false
This imbed file contains the portion of the document that describes the
json support that is provided by the framework.
.fi
&h1(Json Support)
The C++ xAPP framework provides a very lightweight json parser and data
hash facility.
Briefly, a json hash (Jhash) can be established by creating an instance of
the Jhash object with a string of valid json.
The resulting object's functions can then be used to read values from the
resulting hash.
&h2(Creating The Jhash Object)
The Jhash object is created simply by passing a json string to the constructor.
.cc 10l
&ex_start
#include <ricxfcpp/Jhash>
std::string jstring = "{ \"tag\": \"Hello World\" }";
Jhash* jh;
jh = new Jhash( jstring.c_str() );
&ex_end
&fig(The creation of the Jhash object.)
&space
Once the Jhash object has been created any of the methods described in the following
paragraphs can be used to retrieve the data:
&h2(Json Blobs)
Json objects can be nested, and the nesting is supported by this representation.
The approach taken by Jhash is a "directory view" approach, where the "current directory,"
or current &ital(blob,) limits the scope of visible fields.
&space
As an example, the json contained in figure jblob_fig, contains a "root" blob and
two &ital(sub-blobs) (address and lease_info).
&ex_start
{
"lodge_name": "Water Buffalo Lodge 714",
"member_count": 41,
"grand_poobah": "Larry K. Slate",
"attendance": [ 23, 14, 41, 38, 24 ],
"address": {
"street": "16801 Stonway Lane",
"suite": null,
"city": "Bedrock",
"post_code": "45701"
},
"lease_info": {
"owner": "Stonegate Properties",
"amount": 216.49,
"due": "monthly",
"contact:" "Kyle Limestone"
}
}
&ex_end
.gv fig
.sv _fig
&set_fref(jblob_fig:&_fig)
&fig(Sample json with a root and too blobs.)
&space
Upon creation of the Jhash object, the &ital(root) fields, &cw(lodge_name,) &cw(member_count,) and
&cw(grand_poobah) are immediately available.
The fields in the &ital(sub-blobs) are avalable only when the correct blob is selected.
The code sample in figure &fig_blob_sample illustrates how a &ital(sub-blob) is selected.
&ex_start
jh->Set_blob( (char *) "address" ); // select address
jh->Unset_blob(); // return to root
jh->Set_blob( (char *) "lease_info" ); // slect the lease blob
&ex_end
.gv fig
.sv _fig
&set_fref(fig_blob_sample:&_fig)
&fig(Blob selection example.)
&space
Currently, the selected blob must be unset in order to select a blob at the root
level; unset always sets the root blob.
Attempting to use the &cw(Set_blob) function will attempt to select the named blob
from the current blob, and not the root.
&h2(Simple Value Extraction)
Simple values are the expected data types &ital(string, value,) and &ital(boolean.)
This lightweight json parser treats all values as floating point numbers and does not
attempt to maintain a separate integer type.
A fourth type, &ital(null,) is supported to allow the user to expressly check for
a field which is defined but has no value; as opposed to a field that was completely
missing from the data.
The following are the prototypes for the functions which allow values to be extracted:
&half_space
&ex_start
std::string String( const char* name );
float Value( const char* name );
bool Bool( const char* name );
&ex_end
&space
Each of these funcitons returns the value associated with the field with the given &ital(name.)
If the value is missing, the following default values are returned:
&half_space
&indent
&beg_dlist( 1i Helvetica-bold : : 15,80 )
&di(String:) An empty string (.e.g "").
&di(Value:) Zero (e.g 0.0)
&di(bool:) false
&end_dlist
&uindent
&space
If the user needs to disambiguate between a missing value and the default value either the
&cw(Missing) or &cw(Exists) function should be used first.
&h2(Testing For Existing and Missing Fields)
Two functions allow the developer to determine whether or not a field is included in the
json.
Both of these functions work on the current &ital(blob,) therefore it is important to ensure
that the correct blob is selected before using either of these funcitons.
The prototpyes for the &cw(Exists) and &cw(Missing) functions are below:
&ex_start
bool Exists( const char* name );
bool Is_missing( const char* name );
&ex_end
The &cw(Exists) function returns &ital(true) if the field name exists in the json and &ital(false) otherwise.
Conversly, the &cw(Missing) funciton returns &ital(true) when the field name does not exist in the json.
&h2(Testing Field Type)
The &cw(Exists) and &cw(Missing) functions might not be enough for the user code to validate
the data that it has.
To assist with this, several functions allow direct type testing on a field in the current
blob.
The following are the prototypes for these functions:
&ex_start
bool Is_bool( const char* name );
bool Is_null( const char* name );
bool Is_string( const char* name );
bool Is_value( const char* name );
&ex_end
&space
Each of these funcitons return &ital(true) if the field with the given name is of the type
being tested for.
&h2(Arrays)
Arrays are supported in the same manner as simple field values with the addition of the need
to supply an array index when fetching values from the object.
In addition, there is a &ital(length) function which can be used to determine the number
of elements in the named array.
The prototypes for the array based functions are below:
&ex_start
int Array_len( const char* name );
bool Is_bool_ele( const char* name, int eidx );
bool Is_null_ele( const char* name, int eidx );
bool Is_string_ele( const char* name, int eidx );
bool Is_value_ele( const char* name, int eidx );
bool Bool_ele( const char* name, int eidx );
std::string String_ele( const char* name, int eidx );
float Value_ele( const char* name, int eidx );
&ex_end
&space
For each of these functions the &cw(eidx) is the zero based element index which is to
be tested or selected.
&h3(Arrays of Blobs)
An array containing blobs, rather than simiple field value pairs, the blob must
be selected prior to using it, just as a sub-blob needed to be selected.
The &cw(Set_blob_ele) function is used to do this and has the following prototype:
&ex_start
bool Set_blob_ele( const char* name, int eidx );
&ex_end
&space
As with selecting a sub-blob, an unset must be preformed before selecting the next blob.
Figure &array_blob_code_fig illustrates how these functions can be used to read and print
values from the json in figure &array_blob_json_fig.
.cc 8l
&ex_start
"members": [
{ "name": "Fred Flinstone", "member_num": 42 },
{ "name": "Barney Rubble", "member_num": 48 },
{ "name": "Larry K Slate", "member_num": 22 },
{ "name": "Kyle Limestone", "member_num": 49 }
]
&ex_end
.gv fig
&set_fref(array_blob_code_fig:&_fig)
&fig(Json array containing blobs.)
&space
.cc 18l
&ex_start
std::string mname;
float mnum;
int len;
len = jh->Array_len( (char *) "members" );
for( i = 0; i < len; i++ ) {
jh->Set_blob_ele( (char *) "members", i ); // select blob
mname = jh->String( (char *) "name" ); // read values
mnum = jh->Value( (char *) "member_num" );
fprintf( stdout, "%s is member %d\n", mname.c_str(), (int) mnum );
jh->Unset_blob(); // back to root
}
&ex_end
.gv fig
&set_fref(array_blob_json_fig:&_fig)
&fig(Code to process the array of blobs.)
&space