Provide conversions between JSON and bdlat-compatible types.
Outline
Purpose
Provide conversions between JSON and bdlat-compatible types.
Classes
- See also
- baljsn_convertfromjsonoptions, baljsn_converttojsonoptions, baljsn_encoder, bsljsn_decoder
Description
This component provides a mechanism, baljsn::JsonConverter, to convert from a bdlat-compatible object (see Package bdlat ) to a corresponding bdljsn::Json object, and also to convert back from a bdljsn::Json object to a bdlat object.
The conversion to a bdljsn::Json object produces the same result as encoding the bdlat object to a JSON document using baljsn::Encoder and then using bdljsn::JsonUtil::read to construct a bdljsn::Json object from that JSON document – however, using baljsn::JsonConverter avoids the creation of that intermediate document. Conversely, a bdljsn::Json object could be printed as a JSON document (see bdljsn::JsonUtil::write) that is decoded into a bdlat object (see baljsn::Decoder) – but baljsn::JsonConverter does so directly.
Type Mapping
bdlat and JSON provide different type systems that are not entirely congruent. Notably, several bdlat values are converted to JSON strings:
- BDE date and time types are represented as JSON strings in ISO 8601 format.
- Enumerations are converted to a JSON string formatted as their symbolic (programmatic) representation, not their numeric value.
- Floating point values for INF/-INF/Nan are converted to the strings "+inf"/"-inf"/"nan".
Usage
This section illustrates intended use of this component.
Example 1: Encoding a bas_codegen.pl-generated object into 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, populate an Employee object, and encode that object using the baljsn encoder.
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 populate a test::Employee object:
test::Employee employee;
employee.name() = "Bob";
employee.homeAddress().street() = "Lexington Ave";
employee.homeAddress().city() = "New York City";
employee.homeAddress().state() = "New York";
employee.age() = 21;
Then, we will create a baljsn::JsonConverter object:
Definition baljsn_jsonconverter.h:232
Now, we will create a bdljsn::Json object having elements that match the respective elements of employee.
int rc = converter.
convert(&json, employee);
assert(0 == rc);
bsl::string loggedMessages() const
Definition baljsn_jsonconverter.h:1108
int convert(bdljsn::Json *json, const TYPE &value, const ConvertToJsonOptions &options=ConvertToJsonOptions())
Definition baljsn_jsonconverter.h:1009
Definition bdljsn_json.h:1461
Next, we verify that the json object has the expected elements, each containing the expected value, and having the expected type.
assert(employee.name() == json["name"].theString());
assert(employee.homeAddress().street() == json["homeAddress"]["street"]
.theString());
assert(employee.homeAddress().city() == json["homeAddress"]["city"]
.theString());
assert(employee.homeAddress().state() == json["homeAddress"]["state"]
.theString());
int intValue; rc = json["age"]
assert(0 == rc);
assert(employee.age() == intValue);
int asInt(int *result) const
Definition bdljsn_jsonnumber.h:1027
JsonNumber & theNumber()
Definition bdljsn_json.h:5112
Finally, we verify that the json object can be converted back to an Employee object having the same value as the original:
test::Employee employeeFromJson;
rc = converter.
convert(&employeeFromJson, json);
assert(0 == rc);
assert(employee == employeeFromJson);