Rapidjson返回对文档值的引用

Rapidjson returning reference to Document Value

本文关键字:引用 文档 返回 Rapidjson      更新时间:2023-10-16

我在以下方法中遇到了一些问题,我需要一些帮助来找出我做错了什么。

我想在文档中返回对Value的引用。我从函数外部传递Document,这样当我向其中读取json文件时,就不会"丢失它"。

const rapidjson::Value& CTestManager::GetOperations(rapidjson::Document& document)
{
    const Value Null(kObjectType);
    if (m_Tests.empty())
        return Null;
    if (m_current > m_Tests.size() - 1)
        return Null;
    Test& the_test = m_Tests[m_current];
    CMyFile fp(the_test.file.c_str()); // non-Windows use "r"
    if (!fp.is_open())
        return Null;
    u32 operations_count = 0;
    CFileBuffer json(fp);
    FileReadStream is(fp.native_handle(), json, json.size());
    if (document.ParseInsitu<kParseCommentsFlag>(json).HasParseError())
    {
        (...)
    }
    else
    {
        if (!document.IsObject())
        {
            (...)
        }
        else
        {
            auto tests = document.FindMember("td_tests");
            if (tests != document.MemberEnd())
            {
                for (SizeType i = 0; i < tests->value.Size(); i++)
                {
                    const Value& test = tests->value[i];
                    if (test["id"].GetInt() == the_test.id)
                    {
                        auto it = test.FindMember("operations");
                        if (it != test.MemberEnd())
                        {
                            //return it->value; is this legitimate?
                            return test["operations"];
                        }
                        return Null;
                    }
                }
            }
        }
    }
    return Null;
}

我这样称呼它:

Document document;
auto operations = TestManager().GetOperations(document);

当我在函数中检查test["operations"]的值时,我可以看到我所期望的一切(从驻留代码中删除了调试代码)。

当我在函数外检查返回值时,我可以看到它是一个数组(我期望它)。数组中的成员计数也是正确的,但当打印出来时,我只看到垃圾。

当我在方法内部将Value"打印"到字符串时,我会得到我所期望的(即格式良好的json),但当我在外部打印时,所有键都显示为"IIIIIIII",而不是字符串的值会正确显示。

    rapidjson::StringBuffer strbuf2;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer2(strbuf2);
    ops->Accept(writer2);

由于这不起作用,我决定更改方法以接收值作为参数,并像一样对其进行深入复制

u32 CTestManager::GetOperationsEx(rapidjson::Document& document, rapidjson::Value& operations)
{
   (...)
    if (document.ParseInsitu<kParseCommentsFlag>(json).HasParseError())
    {
        (...)
    }
    else
    {
        if (!document.IsObject())
        {
            (...)
        }
        else
        {
            auto tests = document.FindMember("tests");
            if (tests != document.MemberEnd())
            {
                for (SizeType i = 0; i < tests->value.Size(); i++)
                {
                    const Value& test = tests->value[i];
                    if (test["id"].GetInt() == the_test.id)
                    {
                        const Value& opv = test["operations"];
                        Document::AllocatorType& allocator = document.GetAllocator();
                        operations.CopyFrom(opv, allocator);    //would Swap work?
                        return operations.Size();
                    }
                }
            }
        }
    }
    return 0;
}

我这样称呼它:

Document document;
Value operations(kObjectType);
u32 count = TestManager().GetOperationsEx(document, operations);

但是。。。我得到了同样的东西!!!!

我知道这将是一件愚蠢的事情,但我不能把手放在上面!

有什么想法吗?

这种情况下的问题在于ParseInSitu的使用。当任何一个GetOperations存在时,CFileBuffer将失去作用域并被清除。因为json是在文件的缓冲区时进行原位解析的,所以数据也是如此。