1/*! 2\page json Json Handling 3 4<a href="http://www.json.org/">JSON</a> is a simple textual description of a 5data structure. An example of some JSON would be; 6 7\code 8[ "apple", "orange", { "drink": "tonic water", "count" : 123 } ] 9\endcode 10 11This example is a list that contains two strings followed by an "object". The 12term object refers to a construct akin to a "dictionary" or a "map". It is also 13possible for top-level objects to be non-collection types such as strings. The 14following is also valid JSON; 15 16\code 17"fijoa" 18\endcode 19 20This page details how Haiku provides facilities for both parsing as well as 21writing data encoded as Json. 22 23\section parsing-in-memory-model Parsing with Generic In-Memory Model 24 25For some applications, parsing to an in-memory data structure is ideal. In 26such cases, the \c BJson class provides static methods for parsing a block 27of JSON data into a \c BMessage object. The application logic is then able to 28introspect the \c BMessage to obtain values. 29 30\subsection bmessage-structure BMessage Structure 31 32The \c BMessage class has the ability to carry a collection of key-value pairs. 33In the case of a Json object type, the key-value pairs correlate to a JSON 34object or array. In the case of a JSON array type, the key-value pairs are 35the index of the elements in the JSON array represented as strings. 36 37For example, the following JSON array... 38 39\code 40[ "a", "b", "c" ] 41\endcode 42 43...would be represented by the following \c BMessage ; 44 45<table> 46 <tr> 47 <th>Key</th> 48 <th>Value</th> 49 </tr> 50 <tr> 51 <td>\c "0"</td> 52 <td>\c "a"</td> 53 </tr> 54 <tr> 55 <td>\c "1"</td> 56 <td>\c "b"</td> 57 </tr> 58 <tr> 59 <td>\c "2"</td> 60 <td>\c "c"</td> 61 </tr> 62</table> 63 64A Json object that, in its entirety, consists of a non-collection type such as 65a simple string or a boolean is not able to be represented by a \c BMessage ; 66at the top level there must be an array or an object for the parse to be 67successful. 68 69\section parsing-streaming Stream-based Parsing 70 71Streaming is useful in many situations; 72 73 - where handling the parsed data is easier to undertake as a stream of 74 events 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 79 80This architecture is sometimes known as an event-based parser or a "SAX" parser. 81 82The \c BJson class provides a static method that accepts a stream of Json 83data in the form of a \c BDataIO. A \c BJsonEventListener sub-class is also 84supplied and as each Json token is read-in from the stream, it will be 85provided to the listener. The listener must implement three callback methods 86to handle the Json tokens; 87 88<table> 89 <tr> 90 <th>Method</th> 91 <th>Description</th> 92 </tr> 93 <tr> 94 <td>\c Handle(..)</td> 95 <td>Provides JSON events to the listener</td> 96 </tr> 97 <tr> 98 <td>\c HandleError(..)</td> 99 <td>Signals parse or processing errors to the listener</td> 100 </tr> 101 <tr> 102 <td>\c Complete(..)</td> 103 <td>Informs the listener that parsing has completed</td> 104 </tr> 105</table> 106 107Events are embodied in instances of the \c BJsonEvent class and each of 108these has a type. Example types are; 109 110 - \c B_JSON_STRING 111 - \c B_JSON_OBJECT_START 112 - \c B_JSON_TRUE 113 114In this way, the listener is able to interpret the incoming stream of data as 115Json and handle it in some way. 116 117The following Json... 118 119\code 120{"color": "red", "alpha": 0.6} 121\endcode 122 123Would yield the following stream of events; 124 125<table> 126 <tr> 127 <th>Event Type</th> 128 <th>Event Data</th> 129 </tr> 130 <tr> 131 <td>\c B_JSON_OBJECT_START</td> 132 <td>-</td> 133 </tr> 134 <tr> 135 <td>\c B_JSON_OBJECT_NAME</td> 136 <td>"color"</td> 137 </tr> 138 <tr> 139 <td>\c B_JSON_STRING</td> 140 <td>"red"</td> 141 </tr> 142 <tr> 143 <td>\c B_JSON_OBJECT_NAME</td> 144 <td>"alpha"</td> 145 </tr> 146 <tr> 147 <td>\c B_JSON_NUMBER</td> 148 <td>0.6</td> 149 </tr> 150 <tr> 151 <td>\c B_JSON_OBJECT_END</td> 152 <td>-</td> 153 </tr> 154</table> 155 156\subsection parsing-streaming-numbers Number Handling 157 158The Json number literal format does not specify a numeric type such as \c int32 159or \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 162handling as well as convenient accessors for parsing to \c double or \c int64 163types. This provides a high level of flexibility for the client. 164 165\subsection parsing-streaming-stacked-listeners Stacked Listeners 166 167One implementation approach for a listener implement that might be used to 168read a data-transfer-object (DTO) is to create "sub-listeners" that mirror 169the structure of the Json data. 170 171In the following example, a nested data structure is being parsed. 172 173\image html stacked-listeners.svg 174 175A primary-listener is employed called \c ColorGradientsListener. The 176primary-listener accepts Json parse events and will relay them to a 177sub-listener. The sub-listener is implemented to specifically deal with one 178tier of the inbound data. The sub-listeners are structured in a stack where 179the sub-listener at the head of the stack has a pointer to it's parent. The 180primary-listener maintains a pointer to the current head of the stack and will 181direct events to that sub-listener. 182 183In response to events, the sub-listener can take-up the data, pop itself from 184the stack or push additional sub-listeners from the stack. 185 186The same approach has been used in the following classes in a more generic 187manner; 188 189 - \c BJsonTextWriter 190 - \c BJsonMessageWriter 191 192The intention with this approach is that the structure of the event handling 193code in the sub-listeners mirrors that of the data-structure being parsed. 194Hopefully this makes creating the filling of a specific data-model easier even 195when very specific behaviours are required. 196 197From a schema of the data structure it is probably also possible to create 198these sub-listeners and in this way automatically generate the C++ parse 199code as event listeners. 200 201\section writing Writing 202 203In order to render a data-structure as textual Json data, the opposite flow 204occurs; 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 207the outbound Json stream. 208 209\section end-to-end End to End 210 211Because \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; 213producing Json output from Json input. The output will however not include 214inbound whitespace because whitespace is not grammatically significant in Json. 215 216*/