Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component baljsn_formatter
[Package baljsn]

Provide a formatter for encoding data in the JSON format. More...

Namespaces

namespace  baljsn

Detailed Description

Outline
Purpose:
Provide a formatter for encoding data in the JSON format.
Classes:
baljsn::Formatter JSON formatter
See also:
Component baljsn_encoder, Component baljsn_printutil, Component baljsn_simpleformatter
Description:
This component provides a class, baljsn::Formatter, for formatting JSON objects, arrays, and name-value pairs in the JSON encoding format to a specified output stream.
The JSON encoding format (see http://json.org or ECMA-404 standard for more information) specifies a self-describing and simple syntax that is built on two structures:
  • Objects: JSON objects are represented as collections of name value pairs. The Formatter class allows encoding objects by providing the openObject and closeObject methods to open and close an object and the openMember, closeMember, and putValue methods to add members and values to an object.
  • Arrays: JSON arrays are specified as an ordered list of values. The Formatter class provides the openArray and closeArray method to open and close an array. Additionally the Formatter class allows of separation of array items by a comma via the addArrayElementSeparator method.
The Formatter class also provides the ability to specify formatting options at construction. The options that can be provided include the encoding style (compact or pretty), the initial indentation level and spaces per level if encoding in the pretty format.
Valid sequence of operations
  • - - - - - - - - - - - - - The Formatter class does only minimal checking to verify that the sequence of operations called on its object result in a valid JSON document. It is the user's responsibility to ensure that the methods provided by this component are called in the right order.
Usage:
This section illustrates intended use of this component.
Example 1: Encoding a Stock Portfolio in JSON:
Let us say that we have to encode a JSON document with the following information about stocks that we are interested in. For brevity we just show and encode a part of the complete document.
 {
   "Stocks" : [
     {
       "Name" : "International Business Machines Corp",
       "Ticker" : "IBM US Equity",
       "Last Price" : 149.3,
       "Dividend Yield" : 3.95
     },
     {
       "Name" : "Apple Inc",
       "Ticker" : "AAPL US Equity",
       "Last Price" : 205.8,
       "Dividend Yield" : 1.4
     }
   ]
 }
First, we specify the result that we are expecting to get:
  const bsl::string EXPECTED =
      "{\n"
      "  \"Stocks\" : [\n"
      "    {\n"
      "      \"Name\" : \"International Business Machines Corp\",\n"
      "      \"Ticker\" : \"IBM US Equity\",\n"
      "      \"Last Price\" : 149.3,\n"
      "      \"Dividend Yield\" : 3.95\n"
      "    },\n"
      "    {\n"
      "      \"Name\" : \"Apple Inc\",\n"
      "      \"Ticker\" : \"AAPL US Equity\",\n"
      "      \"Last Price\" : 205.8,\n"
      "      \"Dividend Yield\" : 1.4\n"
      "    }\n"
      "  ]\n"
      "}";
Then, to encode this JSON document we create a baljsn::Formatter object. Since we want the document to be written in a pretty, easy to understand format we will specify the true for the usePrettyStyle option and provide an appropriate initial indent level and spaces per level values:
  bsl::ostringstream os;
  baljsn::Formatter formatter(os, true, 0, 2);
Next, we start calling the sequence of methods requires to produce this document. We start with the top level object and add an element named Stocks to it:
  formatter.openObject();
  formatter.openMember("Stocks");
Then, we see that Stocks is an array element so we specify the start of the array:
  formatter.openArray();
Next, each element within Stocks is an object that contains the information for an individual stock. So we have to output an object here:
  formatter.openObject();
We now encode the other elements in the stock object. The closeMember terminates the element by adding a , at the end. For the last element in an object do not call the closeMember method.
  formatter.openMember("Name");
  formatter.putValue("International Business Machines Corp");
  formatter.closeMember();

  formatter.openMember("Ticker");
  formatter.putValue("IBM US Equity");
  formatter.closeMember();

  formatter.openMember("Last Price");
  formatter.putValue(149.3);
  formatter.closeMember();

  formatter.openMember("Dividend Yield");
  formatter.putValue(3.95);
  // Note no call to 'closeMember' for the last element
Then, close the first stock object and separate it from the second one using the addArrayElementSeparator method.
  formatter.closeObject();
  formatter.addArrayElementSeparator();
Next, we add another stock object. But we don't need to separate it as it is the last one.
  formatter.openObject();

  formatter.openMember("Name");
  formatter.putValue("Apple Inc");
  formatter.closeMember();

  formatter.openMember("Ticker");
  formatter.putValue("AAPL US Equity");
  formatter.closeMember();

  formatter.openMember("Last Price");
  formatter.putValue(205.8);
  formatter.closeMember();

  formatter.openMember("Dividend Yield");
  formatter.putValue(1.4);

  formatter.closeObject();
Similarly, we can continue to format the rest of the document. For the purpose of this usage example we will complete this document.
  formatter.closeArray();
  formatter.closeObject();
Once the formatting is complete the written data can be viewed from the stream passed to the formatter at construction.
  if (verbose)
      bsl::cout << os.str() << bsl::endl;
Finally, verify the received result:
  assert(EXPECTED == os.str());