Search code examples
rapidjson

Create a rapidjson::Value from a JSON string


I want to create a rapidjson::Value from a JSON string, e.g., [1,2,3]. Note: this is not a complete JSON object, it's just a JSON array. In Java I can use objectMapper.readTree("[1,2,3]")to create a JsonNode from a String.

My complete C++ code is as the following:

#include <rapidjson/document.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <iostream>

// just for debug
static void print_json_value(const rapidjson::Value &value) {
    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    value.Accept(writer);

    std::cout << buffer.GetString() << std::endl;
}

//TODO: this function probably has a problem
static rapidjson::Value str_to_json(const char* json) {
    rapidjson::Document document;
    document.Parse(json);
    return std::move(document.Move());
}


int main(int argc, char* argv[]) {
    const char* json_text = "[1,2,3]";

    // copy the code of str_to_json() here
    rapidjson::Document document;
    document.Parse(json_text);
    print_json_value(document);  // works

    const rapidjson::Value json_value = str_to_json(json_text);
    assert(json_value.IsArray());
    print_json_value(json_value);  // Assertion failed here

    return 0;
}

Could anyone find out the problem in my function str_to_json() ?

PS: The code above works in GCC 5.1.0 but not in Visual Studio Community 2015.

UPDATE:

According to the suggestion of @Milo Yip, the correct code is as the following:

#include <rapidjson/document.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <iostream>

static void print_json_value(const rapidjson::Value &value) {
    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    value.Accept(writer);

    std::cout << buffer.GetString() << std::endl;
}

static rapidjson::Document str_to_json(const char* json) {
    rapidjson::Document document;
    document.Parse(json);
    return std::move(document);
}


int main(int argc, char* argv[]) {
    const char* json_text = "[1,2,3]";

    // copy the code of str_to_json() here
    rapidjson::Document document;
    document.Parse(json_text);
    print_json_value(document);  // works

    const rapidjson::Document json_value = str_to_json(json_text);
    assert(json_value.IsArray());
    print_json_value(json_value);  // Now works

    return 0;
}

Solution

  • Simple answer: the return type should be rapidjson::Document instead of rapidjson::Value.

    Longer version: A Document contains an allocator to store all the values during parsing. When returning the Value (actually the root of the tree), the local Document object will be destructed and the buffers in the allocator will be released. It is like std::string s = ...; return s.c_str(); inside a function.