| .** 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 |
| |