2 \page json Json Handling
4 <a href="http://www.json.org/">JSON</a> is a simple textual description of a
5 data structure. An example of some JSON would be;
8 [ "apple", "orange", { "drink": "tonic water", "count" : 123 } ]
11 This example is a list that contains two strings followed by an "object". The
12 term object refers to a construct akin to a "dictionary" or a "map". It is also
13 possible for top-level objects to be non-collection types such as strings. The
14 following is also valid JSON;
20 This page details how Haiku provides facilities for both parsing as well as
21 writing data encoded as Json.
23 \section parsing-in-memory-model Parsing with Generic In-Memory Model
25 For some applications, parsing to an in-memory data structure is ideal. In
26 such cases, the \c BJson class provides static methods for parsing a block
27 of JSON data into a \c BMessage object. The application logic is then able to
28 introspect the \c BMessage to obtain values.
30 \subsection bmessage-structure BMessage Structure
32 The \c BMessage class has the ability to carry a collection of key-value pairs.
33 In the case of a Json object type, the key-value pairs correlate to a JSON
34 object or array. In the case of a JSON array type, the key-value pairs are
35 the index of the elements in the JSON array represented as strings.
37 For example, the following JSON array...
43 ...would be represented by the following \c BMessage ;
64 A Json object that, in its entirety, consists of a non-collection type such as
65 a simple string or a boolean is not able to be represented by a \c BMessage ;
66 at the top level there must be an array or an object for the parse to be
69 \section parsing-streaming Stream-based Parsing
71 Streaming is useful in many situations;
73 - where handling the parsed data is easier to undertake as a stream of
75 - where the quantity of input or output data could be non-trivial and
76 holding that quantity of material in memory is undesirable
77 - where being able to start processing a stream of data before the entire
78 payload has arrived is desirable
80 This architecture is sometimes known as an event-based parser or a "SAX" parser.
82 The \c BJson class provides a static method that accepts a stream of Json
83 data in the form of a \c BDataIO. A \c BJsonEventListener sub-class is also
84 supplied and as each Json token is read-in from the stream, it will be
85 provided to the listener. The listener must implement three callback methods
86 to handle the Json tokens;
94 <td>\c Handle(..)</td>
95 <td>Provides JSON events to the listener</td>
98 <td>\c HandleError(..)</td>
99 <td>Signals parse or processing errors to the listener</td>
102 <td>\c Complete(..)</td>
103 <td>Informs the listener that parsing has completed</td>
107 Events are embodied in instances of the \c BJsonEvent class and each of
108 these has a type. Example types are;
111 - \c B_JSON_OBJECT_START
114 In this way, the listener is able to interpret the incoming stream of data as
115 Json and handle it in some way.
117 The following Json...
120 {"color": "red", "alpha": 0.6}
123 Would yield the following stream of events;
131 <td>\c B_JSON_OBJECT_START</td>
135 <td>\c B_JSON_OBJECT_NAME</td>
139 <td>\c B_JSON_STRING</td>
143 <td>\c B_JSON_OBJECT_NAME</td>
147 <td>\c B_JSON_NUMBER</td>
151 <td>\c B_JSON_OBJECT_END</td>
156 \subsection parsing-streaming-numbers Number Handling
158 The Json number literal format does not specify a numeric type such as \c int32
159 or \c double. To cope with the widest range of possibilities, the
160 \c B_JSON_NUMBER event type captures the content as a string and then the
161 \c BJsonEvent object is able to provide the original string for specific
162 handling as well as convenient accessors for parsing to \c double or \c int64
163 types. This provides a high level of flexibility for the client.
165 \subsection parsing-streaming-stacked-listeners Stacked Listeners
167 One implementation approach for a listener implement that might be used to
168 read a data-transfer-object (DTO) is to create "sub-listeners" that mirror
169 the structure of the Json data.
171 In the following example, a nested data structure is being parsed.
173 \image html stacked-listeners.svg
175 A primary-listener is employed called \c ColorGradientsListener. The
176 primary-listener accepts Json parse events and will relay them to a
177 sub-listener. The sub-listener is implemented to specifically deal with one
178 tier of the inbound data. The sub-listeners are structured in a stack where
179 the sub-listener at the head of the stack has a pointer to its parent. The
180 primary-listener maintains a pointer to the current head of the stack and will
181 direct events to that sub-listener.
183 In response to events, the sub-listener can take-up the data, pop itself from
184 the stack or push additional sub-listeners from the stack.
186 The same approach has been used in the following classes in a more generic
190 - \c BJsonMessageWriter
192 The intention with this approach is that the structure of the event handling
193 code in the sub-listeners mirrors that of the data-structure being parsed.
194 Hopefully this makes creating the filling of a specific data-model easier even
195 when very specific behaviours are required.
197 From a schema of the data structure it is probably also possible to create
198 these sub-listeners and in this way automatically generate the C++ parse
199 code as event listeners.
201 \section writing Writing
203 In order to render a data-structure as textual Json data, the opposite flow
204 occurs; events are emitted by the client software into a class
205 \c BJsonTextWriter. This class supports public methods such as
206 \c WriteFalse() , \c WriteObjectStart() and \c WriteString(...) that control
207 the outbound Json stream.
209 \section end-to-end End to End
211 Because \c BJsonTextWriter is accepting JSON parse events, it is also a
212 \c JsonEventListener and so can be used as a listener with the stream parsing;
213 producing Json output from Json input. The output will however not include
214 inbound whitespace because whitespace is not grammatically significant in Json.