rapidjson工具方法返回无效结果,请求逻辑排查帮助
问题分析与修复:rapidjson fetchStringArray方法返回空数组
问题重现
使用rapidjson编写fetchStringArray工具方法时,返回的数组元素不符合预期,测试用例报错返回空数组。以下是相关代码及测试输出:
json.h 代码
template <> std::vector<std::string> fetchStringArray<std::vector<std::string>>(const rapidjson::Value& value){ std::cout<<"Enter\n"; std::vector<std::string> elements; if (!value.IsArray()) { std::cout<<"Early Exit\n"; return elements; } for (auto& item : value.GetArray()) { if (item.IsString()) { elements.push_back(item.GetString()); } } std::cout<<"Success\n"; return elements; } template <> vector<string> fetchStringArray<vector<string>>(const string& jsonString, const string& key){ std::cout<<"2\n"; rapidjson::Document document; std::cout <<"JsonString "<<jsonString<<"\n"; document.Parse(jsonString); if(document.HasMember("key")){ std::cout <<"key found "<<"\n"; } if (document.HasParseError()) { return std::vector<string>(); } return fetchStringArray<vector<string>>(document); } template <class CollectionT> CollectionT fetchStringArray(const string& jsonString, const string& key) { std::cout<<"4\n"; auto values = fetchStringArray<std::vector<std::string>>(jsonString, key); return CollectionT{values.begin(), values.end()}; }
测试文件 jsontests.cpp 代码
/// test fixture. class JsonTests : public ::testing::Test {}; /** * Test fetchStringArray */ TEST_F(JsonTests, test_fetchStringArray) { char key[] = "key"; auto entries = fetchStringArray<std::set<std::string>>(R"({"key":["ONE","TWO"]})", key); ASSERT_EQ(entries.size(), 2u); EXPECT_NE(entries.find("ONE"), entries.end()); EXPECT_NE(entries.find("TWO"), entries.end()); }
测试运行输出
4 2 JsonString {"key":["ONE","TWO"]} key found Enter Early Exit /Foo/test/JsonTestS.cpp:23: Failure Expected: entries.size() Which is: 0 To be equal to: 2u Which is: 2 [ FAILED ] JsonTests.test_fetchStringArray (0 ms)
逻辑漏洞分析
从输出的Early Exit可以看出,传入到数组处理重载的value并非数组类型,根源在第二个模板函数:
- 硬编码检查成员名:代码中用
document.HasMember("key")判断成员是否存在,但实际应该使用传入的key参数,本次测试只是巧合用了"key"才打印了"key found"; - 错误传递JSON对象:最终调用数组处理函数时,传递的是整个JSON文档对象(
document),而不是key对应的数组值。整个JSON是一个对象({"key": [...]}),不是数组,因此触发!value.IsArray()判断,直接返回空数组。
修复方案
修改第二个模板函数,正确使用传入的key参数,并传递对应的值给数组处理函数:
template <> vector<string> fetchStringArray<vector<string>>(const string& jsonString, const string& key){ std::cout<<"2\n"; rapidjson::Document document; std::cout <<"JsonString "<<jsonString<<"\n"; document.Parse(jsonString); if (document.HasParseError()) { return std::vector<string>(); } // 使用传入的key参数检查成员 if(document.HasMember(key.c_str())){ std::cout <<"key found "<<"\n"; // 传递key对应的value给数组处理函数 return fetchStringArray<vector<string>>(document[key.c_str()]); } // 未找到指定key时返回空数组 return std::vector<string>(); }
修复后的预期结果
测试运行时会打印Success,返回包含"ONE"和"TWO"的数组,测试用例通过。
内容的提问来源于stack exchange,提问作者bourne
相关产品推荐
相关产品推荐

