How can I add string pairs to a document of rapidjson

Zen picture Zen · Jan 3, 2016 · Viewed 11.9k times · Source

I want to create a json string using rapidjson. But I got a error: unable to convert std::string to rapidjson::Type.

int x = 111;
string className = "myclass";

Document doc;
auto& allocator = doc.GetAllocator();

doc.AddMember("x", Value().SetInt(x), allocator);
doc.AddMember("className", className, allocator);

unordered_map<string, string>& map = sprite->toMap();
for (const auto& pair : map) {
    Value key(pair.first.c_str(), pair.first.size(), allocator);
    doc.AddMember(key, pair.second, allocator);
}

StringBuffer sb;
Writer<StringBuffer> writer(sb);

doc.Accept(writer);
log("json string: %s", sb.GetString());

Answer

Milo Yip picture Milo Yip · Jan 4, 2016

If #define RAPIDJSON_HAS_STDSTRING 1 (before including rapidjson header files, or defined in compiling flags), there are some extra APIs for std::string.

To make "copy-strings" (allocated duplicates of source strings) of std::string, you can use constructor with allocator:

for (auto& pair : map) {
    rapidjson::Value key(pair.first, allocator);
    rapidjson::Value value(pair.second, allocator);
    doc.AddMember(key, value, allocator);
}

Or make it a single statement:

for (auto& pair : map)
    doc.AddMember(
        rapidjson::Value(pair.first, allocator).Move(),
        rapidjson::Value(pair.second, allocator).Move(),
        allocator);

If you presume that the lifetime of strings are longer than doc, then you can use "const-string" instead, which is simpler and more efficient:

for (auto& pair : map)
    doc.AddMember(
        rapidjson::StringRef(pair.first),
        rapidjson::StringRef(pair.second),
        allocator);

I think the macro RAPIDJSON_HAS_STDSTRING should be documented better...