输出损坏,可能是由于rapidjson :: Document :: Allocator

时间:2016-03-28 14:34:10

标签: c++ rapidjson

我遇到了一些麻烦,我认为是对象所有权。我的目标是创建一个JSON-RPC消息。我想在较低级别实现的是一个对象数组,每个对象都有一个对象error。一切都很顺利,除了那个内部error对象。

您可以在下面找到我的代码的输出。正如您所看到的,error.message的前8个字符被null字符替换。预期输出应为Internal error: Don't know what happened

[{"error":{"code":-32603,"message":"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000 error: Don't know what happened"},"jsonrpc":"2.0","id":null}]

由于每个对象都是在循环内创建并添加到数组中的,因此每次迭代后范围都会丢失,因此我认为它与所有权有关。可能something like this?我试过了我能想到的一切:为循环内的Document对象创建AllocatorTypeerror,复制而不是移动构造所有对象,等等,但我和妈妈有点卡在这里。任何人都可以帮我管理内部error对象的所有权吗?

提前致谢!

我的代码:

void MessageCenter::write_rpc_response(network::Session& session,
        const std::vector<RPCResponse>& rpc_responses)
{
    rapidjson::Document json_responses;
    rapidjson::Document::AllocatorType& alloc = json_responses.GetAllocator();
    json_responses.SetArray();

    std::vector<RPCResponse>::const_iterator iter;
    for (iter = rpc_responses.begin(); iter != rpc_responses.end(); iter++)
    {
        rapidjson::Document resp;
        resp.SetObject();

        // Create error object, based on std::map
        struct { int64_t code = 0; std::string message = ""; } error;
        error.code = -32603;
        error.message = "Internal error: Don't know what happened";

        // Create JSON object, based on the error object
        rapidjson::Value data_object(rapidjson::kObjectType);

        data_object.AddMember("code",
                rapidjson::Value(error.code).Move(), alloc);
        rapidjson::Value error_message(error.message.c_str(),
                error.message.length());
        data_object.AddMember("message", error_message.Move(), alloc);

        resp.AddMember("error", data_object.Move(), alloc);

        // Add JSON-RPC version
        rapidjson::Value jsonrpc_version(iter->jsonrpc.c_str(),
                iter->jsonrpc.length());
        resp.AddMember("jsonrpc", jsonrpc_version.Move(), alloc);

        // Add id: null if 0, int otherwise
        if (iter->id == 0) {
            resp.AddMember("id", rapidjson::Value().Move(), alloc);
        }
        else {
            resp.AddMember("id", rapidjson::Value(iter->id).Move(), alloc);
        }
        json_responses.PushBack(resp, alloc);
    }

    // Write to the session
    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    json_responses.Accept(writer);
    session.Write(buffer.GetString());
}

1 个答案:

答案 0 :(得分:1)

有几个用于构造字符串的API:

//! Constructor for constant string (i.e. do not make a copy of string)
GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }

//! Constructor for constant string (i.e. do not make a copy of string)
explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); }

//! Constructor for copy-string (i.e. do make a copy of string)
GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); }

//! Constructor for copy-string (i.e. do make a copy of string)
GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }

以下代码使用常量字符串版本:

    rapidjson::Value error_message(error.message.c_str(),
            error.message.length());

但显然error将超出范围。您应该使用复制字符串API:

    rapidjson::Value error_message(error.message.c_str(),
            error.message.length(), alloc);

顺便说一下,resp不一定是Document。它可以只是一个Value。但是,如果你总是使用外部分配器,这不会产生错误。