Userver provides classes for reading, working with, and serializing various data formats. Classes for different formats have an almost identical interface. There are common points for customizing parsers and serializers of custom types.
In order for formats::*::Value to be able to represent data as a C++ type, you should write a special function Parse for that C++ type. Parse should be located in the namespace of the type or may be located in the formats::common namespace if the type comes from third-party library that you have no control of:
namespace my_namespace {
struct MyKeyValue {
std::string field1;
int field2;
};
// The function must be declared in the namespace of your type
auto umap = doc["key_d"].As<std::unordered_map<std::string, int>>();
EXPECT_EQ(1, umap["one"]);
EXPECT_EQ(2, umap["two"]);
Those inline helper functions usually work slightly faster than formats::*::ValueBuilder. However, if you need a std::string with JSON the fastest way would be to use the Streaming Serialization. Inline helpers could not be customized for used provided types, unlike other format building types. Inline helpers could produce broken value on bad input because they skip some of the checks, for example a key uniqueness check.
In order for formats::*::ValueBuilder to be able to represent a C++ type in the specified format, you should write a special function Serialize for that C++ type. Serialize should be located in the namespace of the type or may be located in the formats::common namespace if the type comes from third-party library that you have no control of:
namespace my_namespace {
struct MyKeyValue {
std::string field1;
int field2;
};
// The function must be declared in the namespace of your type
For runtime-critical code, it is possible to use streaming serializers. They allow you to serialize several times faster than formats::json::ValueBuilder, but should be used carefully because may produce broken format.