Add json support
[ric-plt/xapp-frame-cpp.git] / doc / src / user / jhash.im
1 .** vim: sw=4 ts=4 et :
2 .if false
3 ==================================================================================
4     Copyright (c) 2020 Nokia
5     Copyright (c) 2020 AT&T Intellectual Property.
6
7    Licensed under the Apache License, Version 2.0 (the "License");
8    you may not use this file except in compliance with the License.
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18 ==================================================================================
19 .fi
20
21
22 .if false
23         This imbed file contains the portion of the document that describes the
24         json support that is provided by the framework.
25 .fi
26
27
28 &h1(Json Support)
29 The C++ xAPP framework provides a  very lightweight json parser and data
30 hash facility.
31 Briefly, a json hash (Jhash) can be established by creating an instance of
32 the Jhash object with a string of valid json.
33 The resulting object's functions can then be used to read values from the
34 resulting hash.
35
36
37 &h2(Creating The Jhash Object)
38 The Jhash object is created simply by passing a json string to the constructor.
39
40 .cc 10l
41 &ex_start
42     #include <ricxfcpp/Jhash>
43
44     std::string jstring = "{ \"tag\": \"Hello World\" }";
45     Jhash*  jh;
46
47     jh =  new Jhash( jstring.c_str() );
48 &ex_end
49 &figure(The creation of the Jhash object.)
50 &space
51
52
53 Once the Jhash object has been created any of the methods described in the following
54 paragraphs can be used to retrieve the data:
55
56 &h2(Json Blobs)
57 Json objects can be nested, and the nesting is supported by this  representation.
58 The approach taken by Jhash is a "directory view" approach, where the "current directory,"
59 or current &ital(blob,) limits the scope of visible fields.
60
61 &space
62 As an example, the json contained in figure jblob_fig, contains a "root" blob and
63 two &ital(sub-blobs) (address and lease_info).
64
65 &ex_start
66     {
67         "lodge_name": "Water Buffalo Lodge 714",
68         "member_count": 41,
69         "grand_poobah": "Larry K. Slate",
70         "attendance":   [ 23, 14, 41, 38, 24 ],
71         "address": {
72             "street":    "16801 Stonway Lane",
73             "suite":     null,
74             "city":      "Bedrock",
75             "post_code": "45701"
76         },
77         "lease_info": {
78             "owner":    "Stonegate Properties",
79             "amount":   216.49,
80             "due":      "monthly",
81             "contact:"  "Kyle Limestone"
82         }
83     }
84 &ex_end
85 .gv fig
86 .sv _fig
87 &set_fref(jblob_fig:&_fig)
88 &figure(Sample json with a root and too blobs.)
89
90 &space
91 Upon creation of the Jhash object, the &ital(root) fields, &cw(lodge_name,) &cw(member_count,) and
92 &cw(grand_poobah) are immediately available.
93 The fields in the &ital(sub-blobs) are avalable only when the correct blob is selected.
94 The code sample in figure &fig_blob_sample illustrates how  a &ital(sub-blob) is selected.
95
96 &ex_start
97     jh->Set_blob( (char *) "address" );     // select address
98     jh->Unset_blob();                       // return to root
99     jh->Set_blob( (char *) "lease_info" );  // slect the lease blob
100 &ex_end
101 .gv fig
102 .sv _fig
103 &set_fref(fig_blob_sample:&_fig)
104 &figure(Blob selection example.)
105 &space
106
107 Currently, the selected blob must be unset in order to select a blob at the root
108 level; unset always sets the root blob.
109 Attempting to use the &cw(Set_blob)  function will attempt to select the named blob
110 from the current blob, and not the root.
111
112 &h2(Simple Value Extraction)
113 Simple values are the expected data types &ital(string, value,) and &ital(boolean.)
114 This lightweight json parser treats all values as floating point numbers and does not
115 attempt to maintain a separate integer type.
116 A fourth type, &ital(null,) is supported to allow the user to expressly check for
117 a field which is defined but has no value; as opposed to a field that was completely
118 missing from the data.
119 The following are the prototypes for the functions which allow values to be extracted:
120
121 &half_space
122 &ex_start
123     std::string String( const char* name );
124     float Value( const char* name );
125     bool Bool( const char* name );
126 &ex_end
127 &space
128
129 Each of these funcitons returns the value associated with the field with the given &ital(name.)
130 If the value is missing, the following default values are returned:
131
132 &half_space
133 &indent
134 &beg_dlist( 1i Helvetica-bold : : 15,80 )
135     &di(String:) An empty string (.e.g "").
136     &di(Value:) Zero (e.g 0.0)
137     &di(bool:) false
138 &end_dlist
139 &uindent
140 &space
141
142 If the user needs to disambiguate between a missing value and the default value either the
143 &cw(Missing) or &cw(Exists) function should be used first.
144
145 &h2(Testing For Existing and Missing Fields)
146 Two functions allow the developer to determine whether or not a field is included in the
147 json.
148 Both of these functions work on the current &ital(blob,) therefore it is important to ensure
149 that the correct blob is selected before using either of these funcitons.
150 The prototpyes for the &cw(Exists) and &cw(Missing) functions are below:
151
152 &ex_start
153     bool Exists( const char* name );
154     bool Is_missing( const char* name );
155 &ex_end
156
157 The &cw(Exists) function returns &ital(true) if the field name exists in the json and &ital(false) otherwise.
158 Conversly, the &cw(Missing) funciton returns &ital(true) when the field name does not exist in the json.
159
160
161 &h2(Testing Field Type)
162 The &cw(Exists) and &cw(Missing) functions might not be enough for the user code to validate
163 the data that it has.
164 To assist with this, several functions allow direct type testing on a field in the current
165 blob.
166 The following are the prototypes for these functions:
167
168 &ex_start
169     bool Is_bool( const char* name );
170     bool Is_null( const char* name );
171     bool Is_string( const char* name );
172     bool Is_value( const char* name );
173 &ex_end
174
175 &space
176 Each of these funcitons return &ital(true) if the field with the given name is of the type
177 being tested for.
178
179
180 &h2(Arrays)
181 Arrays are supported in the same manner as simple field values with the addition of the need
182 to supply an array index when fetching values from the object.
183 In addition, there is a &ital(length) function which can be used to determine the number
184 of elements in the named array.
185 The prototypes for the array based functions are below:
186
187 &ex_start
188     int Array_len( const char* name );
189
190     bool Is_bool_ele( const char* name, int eidx );
191     bool Is_null_ele( const char* name, int eidx );
192     bool Is_string_ele( const char* name, int eidx );
193     bool Is_value_ele( const char* name, int eidx );
194
195     bool Bool_ele( const char* name, int eidx );
196     std::string String_ele( const char* name, int eidx );
197     float Value_ele( const char* name, int eidx );
198 &ex_end
199 &space
200
201 For each of these functions the &cw(eidx) is the zero based element index which is to
202 be tested or selected.
203
204 &h3(Arrays of Blobs)
205 An array containing blobs, rather than simiple field value pairs, the blob must
206 be selected prior to using it, just as a sub-blob needed to be selected.
207 The &cw(Set_blob_ele) function is used to do this and has the following prototype:
208
209 &ex_start
210     bool Set_blob_ele( const char* name, int eidx );
211 &ex_end
212 &space
213
214 As with selecting a sub-blob, an unset must be preformed before selecting the next blob.
215 Figure &array_blob_code_fig illustrates how these functions can be used to read and print
216 values from the json in figure &array_blob_json_fig.
217
218
219 .cc 8l
220 &ex_start
221     "members": [
222         { "name": "Fred Flinstone", "member_num": 42 },
223         { "name": "Barney Rubble", "member_num": 48 },
224         { "name": "Larry K Slate", "member_num": 22 },
225         { "name": "Kyle Limestone", "member_num": 49 }
226     ]
227 &ex_end
228 .gv fig
229 &set_fref(array_blob_code_fig:&_fig)
230 &figure(Json array containing blobs.)
231 &space
232
233
234 .cc 18l
235 &ex_start
236     std::string mname;
237     float mnum;
238     int len;
239
240     len = jh->Array_len( (char *) "members" );
241     for( i = 0; i < len; i++ ) {
242         jh->Set_blob_ele( (char *) "members", i );  // select blob
243
244         mname = jh->String( (char *) "name" );      // read values
245         mnum = jh->Value( (char *) "member_num" );
246         fprintf( stdout, "%s is member %d\n", mname.c_str(), (int) mnum );
247
248         jh->Unset_blob();                           // back to root
249     }
250 &ex_end
251 .gv fig
252 &set_fref(array_blob_json_fig:&_fig)
253 &figure(Code to process the array of blobs.)
254 &space
255