diff --git a/docs/develop/support/json/json.md b/docs/develop/support/json/json.md deleted file mode 100644 index 4b9dfe4b5e..0000000000 --- a/docs/develop/support/json/json.md +++ /dev/null @@ -1,109 +0,0 @@ -# JSON - -[JSON](http://www.json.org/) is a simple textual description of a data structure. An example of some JSON would be; - -``` -[ "apple", "orange", { "drink": "tonic water", "count" : 123 } ] -``` - -## Parsing - -### Generic In-Memory Model - -For some applications, parsing to an in-memory data structure is ideal. In such cases, the ```BJson``` class provides static methods for parsing a block of JSON data into a ```BMessage``` object. - -#### BMessage Structure - -The ```BMessage``` class has the ability to carry a collection of key-value pairs. In the case of a JSON object type, the key-value pairs correlate to the JSON object. In the case of a JSON array type, the key-value pairs are the index of the elements in the JSON array represented as strings. - -For example, the following JSON array... - -``` -[ "a", "b", "c" ] -``` - -...would be represented by the following ```BMessage```; - -|Key|Value| -|---|---| -|"0"|"a"| -|"1"|"b"| -|"2"|"c"| - -A JSON object that, in its entirety, consists of a non-collection type such as a simple string or a boolean is not able to be represented by a ```BMessage```; at the top level there must be an array or an object. - -### Streaming - -Streaming is useful in many situations; - -* where handling the parsed data is easier to undertake as a stream of events -* where the quantity of input or output data could be non-trivial and holding that quantity of material in memory is undesirable -* where being able to start processing a stream of data before the entire payload has arrived is desirable - -This architecture is sometimes known as an event-based parser or a "SAX" parser. - -The ```BJson``` class provides a static method that accepts a stream of JSON data in the form of a ```BDataIO``` and a ```BJsonEventListener``` sub-class. As each token is processed from the stream, it will provided to the listener. The listener must implement three callback methods to handle the JSON parsing; - -|Method|Description| -|---|---| -|Handle(..)|Provides JSON events to the listener| -|HandleError(..)|Signals parse or processing errors to the listener| -|Complete(..)|Informs the listener that parsing has completed| - -Events are embodied in instances of the ```BJsonEvent``` class and each of these has a type. Sample example types are; - -* B_JSON_STRING -* B_JSON_OBJECT_START -* B_JSON_TRUE - -In this way, the listener is able to interpret the incoming stream of data as JSON and handle it in some way. - -The following JSON... - -``` -{"color": "red", "alpha": 0.6} -``` - -Would yield the following stream of events; - -|Event Type|Event Data| -|---|---| -|B_JSON_OBJECT_START|-| -|B_JSON_OBJECT_NAME|"color"| -|B_JSON_STRING|"red"| -|B_JSON_OBJECT_NAME|"alpha"| -|B_JSON_NUMBER|0.6| -|B_JSON_OBJECT_END|-| - -#### Number Handling - -The JSON number literal format does not specify a numeric type such as ```int32``` or ```double```. To cope with the widest range of possibilities, the ```B_JSON_NUMBER``` event type captures the content as a string and then the ```BJsonEvent``` object is able to provide the original string for specific handling as well as convenient accessors for parsing to ```double``` or ```int64``` types. This provides a high level of flexibility for the client. - -#### Stacked Listeners - -One implementation approach for the listener used to read a data-transfer-object (DTO) is to create "sub-listeners" that mirror the structure of the JSON. - -In the following example, a nested data structure is being parsed. - -![Stacked Listeners](stacked-listeners.svg) - -A primary-listener is employed called ```ColorGradientsListener```. The primary-listener accepts JSON parse events and will relay them to a sub-listener. The sub-listener is implemented to specifically deal with one tier of the inbound data. The sub-listeners are structured in a stack where the sub-listener at the head of the stack has a pointer to it's parent. The primary-listener maintains a pointer to the current head of the stack and will direct events to that sub-listener. - -In response to events, the sub-listener can take-up the data, pop itself from the stack or push additional sub-listeners from the stack. - -The same approach has been used in the following classes in a more generic manner; - -* BJsonTextWriter -* BJsonMessageWriter - -The intention with this approach is that the structure of the event handling code in the sub-listeners mirrors that of the data-structure being parsed. Hopefully this makes creating the filling of a specific data-model easier even when very specific behaviours are required. - - From a schema of the data structure it is _probably_ also possible to create these sub-listeners and in this way automatically generate the C++ parse code as event listeners. - -## Writing - -In order to render a data-structure as JSON data, the opposite occurs; events are emitted by the client software into a class ```BJsonTextWriter```. This class supports public methods such as ```WriteFalse()```, ```WriteObjectStart()``` and ```WriteString(...)``` that control the outbound JSON stream. - -### End to End - -Because ```BJsonTextWriter``` is accepting JSON parse events, it is also a ```JsonEventListener``` and so can be used as a listener with the stream parsing; producing JSON output from JSON input. The output will however not include inbound whitespace because whitespace is not grammatically significant in JSON. \ No newline at end of file diff --git a/docs/user/Doxyfile b/docs/user/Doxyfile index 3ae8fa13eb..216014f79c 100644 --- a/docs/user/Doxyfile +++ b/docs/user/Doxyfile @@ -784,6 +784,7 @@ INPUT = . \ midi2 \ net \ posix \ + shared \ storage \ support \ translation \ @@ -905,7 +906,8 @@ IMAGE_PATH = . \ keyboard \ midi2/images \ net/images \ - storage/images + storage/images \ + shared/images # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program diff --git a/docs/user/book.dox b/docs/user/book.dox index 2209da5f3f..7ad33fa9cd 100644 --- a/docs/user/book.dox +++ b/docs/user/book.dox @@ -61,6 +61,7 @@ - \ref drivers - \ref keyboard + - \ref json */ ///// Define main kits ///// @@ -610,4 +611,7 @@ snooze_until(time - Latency(), B_SYSTEM_TIMEBASE); /*! \defgroup drivers Device Drivers + + \defgroup json Json Handling + \brief Provides for parsing and writing of data in Json encoding. */ diff --git a/docs/develop/support/json/stacked-listeners.svg b/docs/user/shared/images/stacked-listeners.svg similarity index 100% rename from docs/develop/support/json/stacked-listeners.svg rename to docs/user/shared/images/stacked-listeners.svg diff --git a/docs/user/shared/json.dox b/docs/user/shared/json.dox new file mode 100644 index 0000000000..9e58560be5 --- /dev/null +++ b/docs/user/shared/json.dox @@ -0,0 +1,216 @@ +/*! +\page json Json Handling + +JSON is a simple textual description of a +data structure. An example of some JSON would be; + +\code +[ "apple", "orange", { "drink": "tonic water", "count" : 123 } ] +\endcode + +This example is a list that contains two strings followed by an "object". The +term object refers to a construct akin to a "dictionary" or a "map". It is also +possible for top-level objects to be non-collection types such as strings. The +following is also valid JSON; + +\code +"fijoa" +\endcode + +This page details how Haiku provides facilities for both parsing as well as +writing data encoded as Json. + +\section parsing-in-memory-model Parsing with Generic In-Memory Model + +For some applications, parsing to an in-memory data structure is ideal. In +such cases, the \c BJson class provides static methods for parsing a block +of JSON data into a \c BMessage object. The application logic is then able to +introspect the \c BMessage to obtain values. + +\subsection bmessage-structure BMessage Structure + +The \c BMessage class has the ability to carry a collection of key-value pairs. +In the case of a Json object type, the key-value pairs correlate to a JSON +object or array. In the case of a JSON array type, the key-value pairs are +the index of the elements in the JSON array represented as strings. + +For example, the following JSON array... + +\code +[ "a", "b", "c" ] +\endcode + +...would be represented by the following \c BMessage ; + + + + + + + + + + + + + + + + + + +
KeyValue
\c "0"\c "a"
\c "1"\c "b"
\c "2"\c "c"
+ +A Json object that, in its entirety, consists of a non-collection type such as +a simple string or a boolean is not able to be represented by a \c BMessage ; +at the top level there must be an array or an object for the parse to be +successful. + +\section parsing-streaming Stream-based Parsing + +Streaming is useful in many situations; + + - where handling the parsed data is easier to undertake as a stream of + events + - where the quantity of input or output data could be non-trivial and + holding that quantity of material in memory is undesirable + - where being able to start processing a stream of data before the entire + payload has arrived is desirable + +This architecture is sometimes known as an event-based parser or a "SAX" parser. + +The \c BJson class provides a static method that accepts a stream of Json +data in the form of a \c BDataIO. A \c BJsonEventListener sub-class is also +supplied and as each Json token is read-in from the stream, it will be +provided to the listener. The listener must implement three callback methods +to handle the Json tokens; + + + + + + + + + + + + + + + + + + +
MethodDescription
\c Handle(..)Provides JSON events to the listener
\c HandleError(..)Signals parse or processing errors to the listener
\c Complete(..)Informs the listener that parsing has completed
+ +Events are embodied in instances of the \c BJsonEvent class and each of +these has a type. Example types are; + + - \c B_JSON_STRING + - \c B_JSON_OBJECT_START + - \c B_JSON_TRUE + +In this way, the listener is able to interpret the incoming stream of data as +Json and handle it in some way. + +The following Json... + +\code +{"color": "red", "alpha": 0.6} +\endcode + +Would yield the following stream of events; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Event TypeEvent Data
\c B_JSON_OBJECT_START-
\c B_JSON_OBJECT_NAME"color"
\c B_JSON_STRING"red"
\c B_JSON_OBJECT_NAME"alpha"
\c B_JSON_NUMBER0.6
\c B_JSON_OBJECT_END-
+ +\subsection parsing-streaming-numbers Number Handling + +The Json number literal format does not specify a numeric type such as \c int32 +or \c double. To cope with the widest range of possibilities, the +\c B_JSON_NUMBER event type captures the content as a string and then the +\c BJsonEvent object is able to provide the original string for specific +handling as well as convenient accessors for parsing to \c double or \c int64 +types. This provides a high level of flexibility for the client. + +\subsection parsing-streaming-stacked-listeners Stacked Listeners + +One implementation approach for a listener implement that might be used to +read a data-transfer-object (DTO) is to create "sub-listeners" that mirror +the structure of the Json data. + +In the following example, a nested data structure is being parsed. + +\image html stacked-listeners.svg + +A primary-listener is employed called \c ColorGradientsListener. The +primary-listener accepts Json parse events and will relay them to a +sub-listener. The sub-listener is implemented to specifically deal with one +tier of the inbound data. The sub-listeners are structured in a stack where +the sub-listener at the head of the stack has a pointer to it's parent. The +primary-listener maintains a pointer to the current head of the stack and will +direct events to that sub-listener. + +In response to events, the sub-listener can take-up the data, pop itself from +the stack or push additional sub-listeners from the stack. + +The same approach has been used in the following classes in a more generic +manner; + + - \c BJsonTextWriter + - \c BJsonMessageWriter + +The intention with this approach is that the structure of the event handling +code in the sub-listeners mirrors that of the data-structure being parsed. +Hopefully this makes creating the filling of a specific data-model easier even +when very specific behaviours are required. + +From a schema of the data structure it is probably also possible to create +these sub-listeners and in this way automatically generate the C++ parse +code as event listeners. + +\section writing Writing + +In order to render a data-structure as textual Json data, the opposite flow +occurs; events are emitted by the client software into a class +\c BJsonTextWriter. This class supports public methods such as +\c WriteFalse() , \c WriteObjectStart() and \c WriteString(...) that control +the outbound Json stream. + +\section end-to-end End to End + +Because \c BJsonTextWriter is accepting JSON parse events, it is also a +\c JsonEventListener and so can be used as a listener with the stream parsing; +producing Json output from Json input. The output will however not include +inbound whitespace because whitespace is not grammatically significant in Json. + +*/ \ No newline at end of file