Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component baljsn_simpleformatter
[Package baljsn]

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

Namespaces

namespace  baljsn

Detailed Description

Outline
Purpose:
Provide a simple formatter for encoding data in the JSON format.
Classes:
baljsn::SimpleFormatter a mechanism to encode data into JSON
See also:
Component baljsn_encoder, Component baljsn_formatter, Component baljsn_printutil
Description:
This component provides a class, baljsn::SimpleFormatter, for rendering JSON conforming text for objects, arrays, and various scalar types.
This component provides an interface that is easier to use, and renders more readable "pretty" JSON, than baljsn::Formatter. Clients are encouraged to use baljsn::SimpleFormatter instead of baljsn::Formatter (see Comparison to baljsn::Formatter).
The SimpleFormatter 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.
Comparison to baljsn::Formatter:
API Comparison:
Here is the side-by-side sequence of calls to create the following JSON using both components, assuming an existing stream os:
  {
    "Object" : {
      "Field 1" : 1,
      "Field 2" : null
    },
    "Array" : [
      1,
      "string",
      [],
      [
        [
          {
          }
        ]
      ]
    ],
    "True" : true
  }
Some extra indentation has been added in these examples to show the various open/close call nesting levels.
           Formatter                |             SimpleFormatter
 -----------------------------------+----------------------------------------
 baljsn::Formatter f(os);           | baljsn::SimpleFormatter sf(os);
                                    |
 f.openObject();                    | sf.openObject();
                                    |
  f.openMember("Object");           |  sf.openObject("Object");
   f.openObject();                  |   sf.addValue("Field 1", 1);
    f.openMember("Field 1");        |   sf.addNullValue("Field 2");
     f.putValue(1);                 |  sf.closeObject();
    f.closeMember();                |
    f.openMember("Field 2");        |  sf.openArray("Array");
     f.putNullValue();              |   sf.addValue(1);        // No name
    // Must remember NOT to call    |   sf.addValue("string"); // No name
    // closeMember here!            |   sf.openArray(e_EMPTY_ARRAY_FORMAT);
   f.closeObject();                 |   sf.closeArray(e_EMPTY_ARRAY_FORMAT);
  f.closeMember();                  |   sf.openArray();
                                    |    sf.openArray();
  f.openMember("Array");            |     sf.openObject();
   f.openArray();                   |     sf.closeObject();
    f.putValue(1);                  |    sf.closeArray();
    f.addArrayElementSeparator();   |   sf.closeArray();
    f.putValue("string");           |  sf.closeArray();
    f.addArrayElementSeparator();   |
    f.openArray(true);              |  sf.addValue("True", true);
    f.closeArray(true);             | sf.closeObject();
    f.addArrayElementSeparator();   |
    f.openArray();                  |
     f.openArray();                 |
      f.openObject();               |
      f.closeObject();              |
     f.closeArray();                |
    f.closeArray();                 |
                                    |
    // Must remember NOT to call    |
    // addArrayElementSeparator     |
    // here!                        |
   f.closeArray();                  |
  f.closeMember();                  |
                                    |
  f.openMember("True");             |
   f.putValue(true);                |
  // Must remember NOT to call      |
  // closeMember here!              |
                                    |
 f.closeObject();                   |
 -----------------------------------+----------------------------------------
JSON Format ----------- 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 SimpleFormatter class allows encoding objects by providing the openObject and closeObject methods to open and close an object and overloads for openObject, openArray, addValue and addNullValue which take a name to specify the named fields in the object, or the use of the addMemberName manipulator followed by the overloads of openObject, openArray, addValue, and addNullValue which do not take a name.
  • Arrays: JSON arrays are specified as an ordered list of values. The SimpleFormatter class provides the openArray and closeArray method to open and close an array, as well as overloads for openObject, openArray, addValue and addNullValue which do not take a name for array elements.
The SimpleFormatter class 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.
Usage:
This section illustrates intended use of this component.
Example 1: Encoding a Stock Portfolio in JSON:
Let us suppose we have to encode a JSON document containing information about a small portfolio of stocks. The eventual data we want to encode is represented by the following JSON string (which is the expected output of the encoding process):
First, we specify the result that we are expecting to get:
{
  const bsl::string EXPECTED = R"JSON({
    "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
      }
    ]
  })JSON";
Then, to encode this JSON document we create a baljsn::SimpleFormatter object. Since we want the document to be written in a pretty, easy to understand format we will specify true for the usePrettyStyle option and provide an appropriate initial indent level and spaces per level values:
  bsl::ostringstream      os;
  baljsn::EncoderOptions  encoderOptions;

  encoderOptions.setEncodingStyle(baljsn::EncoderOptions::e_PRETTY);
  encoderOptions.setSpacesPerLevel(2);

  baljsn::SimpleFormatter formatter(os, encoderOptions);
Next, we encode the start of the top level object, and open the first member "Stocks" (which holds an array of stock information):
  formatter.openObject();
  formatter.openArray("Stocks");
Next, we render each element within the array of "Stocks" as an object that contains information for an individual stock:
  formatter.openObject();
We now encode the other elements in the stock object.
  formatter.addValue("Name", "International Business Machines Corp");
  formatter.addValue("Ticker", "IBM US Equity");
  formatter.addValue("Last Price", 149.3);
  formatter.addValue("Dividend Yield", 3.95);
Then, close the first stock object.
  formatter.closeObject();
Next, we add another stock object.
  formatter.openObject();

  formatter.addValue("Name", "Apple Inc");
  formatter.addValue("Ticker", "AAPL US Equity");
  formatter.addValue("Last Price", 205.8);
  formatter.addValue("Dividend Yield", 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());
}
Example 2: Encoding an array:
Let us say we want to encode an array of various values.
First, we create our formatter as we did above:
{
  bsl::ostringstream      os;
  baljsn::EncoderOptions  encoderOptions;

  encoderOptions.setEncodingStyle(baljsn::EncoderOptions::e_PRETTY);
  encoderOptions.setSpacesPerLevel(2);

  baljsn::SimpleFormatter formatter(os, encoderOptions);
Then we open our array.
  formatter.openArray();
Next, we populate the array with a series of unnamed values. Named values are only used in objects, not arrays.
  formatter.addValue("First value");
  formatter.addValue(2);
  formatter.addValue(3);
Then, we demonstrate that arrays can be nested, opening another level of array, populating it, and closing it:
  formatter.openArray();
  formatter.addValue("First value of inner array");
  formatter.addValue(3.14159);
  formatter.closeArray();
Arrays can also contain (unnamed) objects:
  formatter.openObject();
Next, we add (named) values to our object:
  formatter.addValue("Greeting", "Hello from the first inner object");
  formatter.addValue("PI approximation", 3.14);
  // We could, similarly, add nested named objects and/or named arrays
Then we close the nested object:
  formatter.closeObject();
Finally, we close the outer array:
  formatter.closeArray();
}