BDE 4.14.0 Production release
Loading...
Searching...
No Matches
baljsn_decoder

Detailed Description

Outline

Purpose

Provide a JSON decoder for bdeat compatible types.

Classes

See also
baljsn_decoderoptions, balsjn_decoderoptionsutil, baljsn_encoder, baljsn_parserutil, baljsn_parser

Description

This component provides a class, baljsn::Decoder, for decoding value-semantic objects in the JSON format. In particular, the class contains a parameterized decode function that decodes an object from a specified stream. There are two overloaded versions of this function:

This component can be used with types that support the bdeat framework (see the bdeat package for details), which is a compile-time interface for manipulating struct-like and union-like objects. In particular, types generated by the bas_codegen.pl tool, and other dynamic types, can be decoded using this class. The decode function can be invoked on any object that satisfies the requirements of a sequence, choice, or array object as defined in the bdlat_sequencefunctions , bdlat_choicefunctions , and bdlat_arrayfunctions components.

Although the JSON format is easy to read and write and is very useful for debugging, it is relatively expensive to encode and decode and relatively bulky to transmit. It is more efficient to use a binary encoding (such as BER) if the encoding format is under your control (see balber_berdecoder ).

Refer to the details of the JSON encoding format supported by this decoder in the package documentation file (doc/baljsn.txt).

validateInputIsUtf8 Option

The baljsn::DecoderOption parameter of the decode function has a configuration option named validateInputIsUtf8. If this option is true, the decode function will succeed only if the encoding of the JSON data is UTF-8, which the JSON specification requires. If the option is false, decode will not validate that the encoding of the JSON data is UTF-8, and may succeed even if the data does not satisfy the UTF-8 validity requirement of the JSON specification. This option primarily affects the acceptance of string literals, which are the parts of JSON documents that may have rational justification for having non-UTF-8, and therefore invalid, content.

Ideally, users should set validateInputIsUtf8 to true. However, some legacy applications currently might be trafficking in JSON that contains non-UTF-8 with no adverse effects to their clients. Consequently, this option is false by default to maintain backward compatibility.

Strict Conformance

The baljsn::Decoder class allows several convenient variances from the JSON grammar as described in RFC8259 (see https://www.rfc-editor.org/rfc/rfc8259). If strict conformance is needed, users should use the read overloads that accept a baljsn::DecoderOptions object and set the following attributes to the values shown below:

validateInputIsUtf8() == true;
allowConsecutiveSeparators() == false;
allowFormFeedAsWhitespace() == false;
allowUnescapedControlCharacters() == false;

See also {bdljsn_tokenizer |Strict Conformance}.

Usage

This section illustrates intended use of this component.

Example 1: Decoding into a bas_codegen.pl-generated from data in JSON

Consider that we want to exchange an employee's information between two processes. To allow this information exchange we will define the XML schema representation for that class, use bas_codegen.pl to create the Employee class for storing that information, and decode into that object using the baljsn decoder.

First, we will define the XML schema inside a file called employee.xsd:

<?xml version='1.0' encoding='UTF-8'?>
<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'
xmlns:test='http://bloomberg.com/schemas/test'
targetNamespace='http://bloomberg.com/schemas/test'
elementFormDefault='unqualified'>
<xs:complexType name='Address'>
<xs:sequence>
<xs:element name='street' type='xs:string'/>
<xs:element name='city' type='xs:string'/>
<xs:element name='state' type='xs:string'/>
</xs:sequence>
</xs:complexType>
<xs:complexType name='Employee'>
<xs:sequence>
<xs:element name='name' type='xs:string'/>
<xs:element name='homeAddress' type='test:Address'/>
<xs:element name='age' type='xs:int'/>
</xs:sequence>
</xs:complexType>
<xs:element name='Employee' type='test:Employee'/>
</xs:schema>

Then, we will use the bas_codegen.pl tool, to generate the C++ classes for this schema. The following command will generate the header and implementation files for the all the classes in the test_messages components in the current directory:

$ bas_codegen.pl -m msg -p test xsdfile.xsd

Next, we will create a test::Employee object:

test::Employee employee;

Then, we will create a baljsn::Decoder object:

Definition baljsn_decoder.h:254

Next, we will specify the input data provided to the decoder:

const char INPUT[] = "{\"name\":\"Bob\",\"homeAddress\":{\"street\":"
"\"Lexington Ave\",\"city\":\"New York City\","
"\"state\":\"New York\"},\"age\":21}";
Definition bslstl_istringstream.h:176

Now, we will decode this object using the decode function of the baljsn decoder by providing it a baljsn::DecoderOptions object. The decoder options allow us to specify that unknown elements should not be skipped. Setting this option to false will result in the decoder returning an error on encountering an unknown element:

options.setSkipUnknownElements(false);
const int rc = decoder.decode(is, &employee, options);
assert(!rc);
assert(is);
Definition baljsn_decoderoptions.h:153
void setSkipUnknownElements(bool value)
Definition baljsn_decoderoptions.h:570
int decode(bsl::streambuf *streamBuf, TYPE *value, const DecoderOptions &options)
Definition baljsn_decoder.h:1000

Finally, we will verify that the decoded object is as expected:

assert("Bob" == employee.name());
assert("Lexington Ave" == employee.homeAddress().street());
assert("New York City" == employee.homeAddress().city());
assert("New York" == employee.homeAddress().state());
assert(21 == employee.age());