Add support for config file parsing and watching
[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 .ca start jhash_obj.ca
41 &ex_start
42     #include <ricxfcpp/Jhash.hpp>
43
44     std::string jstring = "{ \"tag\": \"Hello World\" }";
45     Jhash*  jh;
46
47     jh =  new Jhash( jstring.c_str() );
48 &ex_end
49 &fig_cen(The creation of the Jhash object.)
50 &space
51 .ca end
52 &ifroom( 2.5 : jhash_obj.ca )
53
54
55 Once the Jhash object has been created any of the methods described in the following
56 paragraphs can be used to retrieve the data:
57
58 &h2(Json Blobs)
59 Json objects can be nested, and the nesting is supported by this  representation.
60 The approach taken by Jhash is a "directory view" approach, where the "current directory,"
61 or current &ital(blob,) limits the scope of visible fields.
62
63 &space
64 As an example, the json contained in figure &jblob_fig, contains a "root" blob and
65 two &ital(sub-blobs) (address and lease_info).
66 &half_space
67
68 .ca start blob_ex.ca
69 &ex_start
70     {
71         "lodge_name": "Water Buffalo Lodge 714",
72         "member_count": 41,
73         "grand_poobah": "Larry K. Slate",
74         "attendance":   [ 23, 14, 41, 38, 24 ],
75         "address": {
76             "street":    "16801 Stonway Lane",
77             "suite":     null,
78             "city":      "Bedrock",
79             "post_code": "45701"
80         },
81         "lease_info": {
82             "owner":    "Stonegate Properties",
83             "amount":   216.49,
84             "due":      "monthly",
85             "contact:"  "Kyle Limestone"
86         }
87     }
88 &ex_end
89 &export_fig( jblob_fig )
90 &fig_cen(Sample json with a root and two blobs.)
91 &space
92 .ca end
93 &ifroom( 3i : blob_ex.ca )
94
95
96 Upon creation of the Jhash object, the &ital(root) fields, &cw(lodge_name,) &cw(member_count,) and
97 &cw(grand_poobah) are immediately available.
98 The fields in the &ital(sub-blobs) are available only when the correct blob is selected.
99 The code sample in figure &fig_blob_sample illustrates how  a &ital(sub-blob) is selected.
100
101 &ex_start
102     jh->Set_blob( (char *) "address" );     // select address
103     jh->Unset_blob();                       // return to root
104     jh->Set_blob( (char *) "lease_info" );  // select the lease blob
105 &ex_end
106 .sv export_fig
107 &export_fig( fig_blob_sample )
108 &fig_cen(Blob selection example.)
109 &space
110
111 Currently, the selected blob must be unset in order to select a blob at the root
112 level; unset always sets the root blob.
113 Attempting to use the &cw(Set_blob)  function will attempt to select the named blob
114 from the current blob, and not the root.
115
116 &h2(Simple Value Extraction)
117 Simple values are the expected data types &ital(string, value,) and &ital(boolean.)
118 This lightweight json parser treats all values as floating point numbers and does not
119 attempt to maintain a separate integer type.
120 A fourth type, &ital(null,) is supported to allow the user to expressly check for
121 a field which is defined but has no value; as opposed to a field that was completely
122 missing from the data.
123 The following are the prototypes for the functions which allow values to be extracted:
124
125 &half_space
126 &ex_start
127     std::string String( const char* name );
128     float Value( const char* name );
129     bool Bool( const char* name );
130 &ex_end
131 &space
132
133 Each of these functions returns the value associated with the field with the given &ital(name.)
134 If the value is missing, the following default values are returned:
135
136 &half_space
137 &indent
138 &beg_dlist( 1i Helvetica-bold : : 15,80 )
139     &di(String:) An empty string (.e.g "").
140     &di(Value:) Zero (e.g 0.0)
141     &di(bool:) false
142 &end_dlist
143 &uindent
144 &space
145
146 If the user needs to disambiguate between a missing value and the default value either the
147 &cw(Missing) or &cw(Exists) function should be used first.
148
149 &h2(Testing For Existing and Missing Fields)
150 Two functions allow the developer to determine whether or not a field is included in the
151 json.
152 Both of these functions work on the current &ital(blob,) therefore it is important to ensure
153 that the correct blob is selected before using either of these functions.
154 The prototypes for the &cw(Exists) and &cw(Missing) functions are below:
155
156 &ex_start
157     bool Exists( const char* name );
158     bool Is_missing( const char* name );
159 &ex_end
160
161 The &cw(Exists) function returns &ital(true) if the field name exists in the json and &ital(false) otherwise.
162 Conversely, the &cw(Missing) function returns &ital(true) when the field name does not exist in the json.
163
164
165 &h2(Testing Field Type)
166 The &cw(Exists) and &cw(Missing) functions might not be enough for the user code to validate
167 the data that it has.
168 To assist with this, several functions allow direct type testing on a field in the current
169 blob.
170 The following are the prototypes for these functions:
171
172 &ex_start
173     bool Is_bool( const char* name );
174     bool Is_null( const char* name );
175     bool Is_string( const char* name );
176     bool Is_value( const char* name );
177 &ex_end
178
179 &space
180 Each of these functions return &ital(true) if the field with the given name is of the type
181 being tested for.
182
183
184 &h2(Arrays)
185 Arrays are supported in the same manner as simple field values with the addition of the need
186 to supply an array index when fetching values from the object.
187 In addition, there is a &ital(length) function which can be used to determine the number
188 of elements in the named array.
189 The prototypes for the array based functions are below:
190
191 &ex_start
192     int Array_len( const char* name );
193
194     bool Is_bool_ele( const char* name, int eidx );
195     bool Is_null_ele( const char* name, int eidx );
196     bool Is_string_ele( const char* name, int eidx );
197     bool Is_value_ele( const char* name, int eidx );
198
199     bool Bool_ele( const char* name, int eidx );
200     std::string String_ele( const char* name, int eidx );
201     float Value_ele( const char* name, int eidx );
202 &ex_end
203 &space
204
205 For each of these functions the &cw(eidx) is the zero based element index which is to
206 be tested or selected.
207
208 &h3(Arrays of Blobs)
209 An array containing blobs, rather than simple field value pairs, the blob must
210 be selected prior to using it, just as a sub-blob needed to be selected.
211 The &cw(Set_blob_ele) function is used to do this and has the following prototype:
212
213 &ex_start
214     bool Set_blob_ele( const char* name, int eidx );
215 &ex_end
216 &space
217
218 As with selecting a sub-blob, an unset must be performed before selecting the next blob.
219 Figure &array_blob_code_fig illustrates how these functions can be used to read and print
220 values from the json in figure &array_blob_json_fig.
221
222
223 .cc 8l
224 &ex_start
225     "members": [
226         { "name": "Fred Flinstone", "member_num": 42 },
227         { "name": "Barney Rubble", "member_num": 48 },
228         { "name": "Larry K Slate", "member_num": 22 },
229         { "name": "Kyle Limestone", "member_num": 49 }
230     ]
231 &ex_end
232 &export_fig(array_blob_code_fig)
233 &fig_cen(Json array containing blobs.)
234 &space
235
236
237 .ca start blobs.ca
238 &ex_start
239     std::string mname;
240     float mnum;
241     int len;
242
243     len = jh->Array_len( (char *) "members" );
244     for( i = 0; i < len; i++ ) {
245         jh->Set_blob_ele( (char *) "members", i );  // select blob
246
247         mname = jh->String( (char *) "name" );      // read values
248         mnum = jh->Value( (char *) "member_num" );
249         fprintf( stdout, "%s is member %d\n", mname.c_str(), (int) mnum );
250
251         jh->Unset_blob();                           // back to root
252     }
253 &ex_end
254 &export_fig(array_blob_json_fig )
255 &fig_cen(Code to process the array of blobs.)
256 &space
257 .ca end
258 &ifroom( 3 : blobs.ca )
259