Я знаю, что это может показаться странным вопросом, но вход моего алгоритма представляет собой поток JSON строк, составленных из синтаксически правильных блоков JSON, по крайней мере для всех блоков, кроме этого. Блок в потоке имеет такую структуру:
{
"comment",
{
"author":"X",
"body":"Hello world",
"json_metadata":"{\"tags\":[\"hello, world\"],\"community\":\"programming\",\"app\":\"application_for_publish\"}",
"parent_author":"waggy6",
"parent_permlink":"programming_in_c",
"permlink":"re-author-programming_in_c-20180916t035418244z",
"title":"some_title"
}
}
Итак, все работает нормально, вплоть до прибытия в этот блок, что я не знаю, как анализировать. Поле, которое доставляет мне неприятности, это "json_metadata"
one:
{
"comment",
{
"author": "Y",
"body": "Hello another world!",
"json_metadata": "\"{\\\"tags\\\":[\\\"hello\\\",\\\"world\\\"],\\\"app\\\":\\\"application_for_publish_content\\\",\\\"format\\\":\\\"markdown+html\\\",\\\"pollid\\\":\\\"p_id\\\",\\\"image\\\":[\\\"https://un.useful.url/path/image.png\\\"]}\"",
"parent_author": "",
"parent_permlink": "helloworld",
"permlink": "hello_world_programming_in_c-2017319t94958596z",
"title": "Hello World in C!"
}
}
Как будто это поле было проанализировано дважды, когда были получены данные. Я использую rapidjson
в качестве инструмента синтаксического анализа, в C ++. Часть кода, связанная с этой проблемой, выглядит следующим образом:
static std::string parseNode(const Value &node){
string toret = "";
if (node.IsBool()) toret = toret + to_string(node.GetBool());
else if (node.IsInt()) toret = toret + to_string(node.GetInt());
else if (node.IsUint()) toret = toret + to_string(node.GetUint());
else if (node.IsInt64()) toret = toret + to_string(node.GetInt64());
else if (node.IsUint64()) toret = toret + to_string(node.GetUint64());
else if (node.IsDouble()) toret = toret + to_string(node.GetDouble());
else if (node.IsString()) toret = toret + node.GetString();
else if (node.IsArray()) toret = toret + parseArray(node); // parse the given array
else if (node.IsObject()) toret = toret + parseObject(node); // parse the given object
return toret;
}
...
std::string search_member(Value& js, std::string member){
Value::ConstMemberIterator itr = js.FindMember(member.c_str());
std::string els = "";
if(itr != js.MemberEnd())
els = parseNode(itr->value) + " ";
return els;
}
...
// op_struct type is Value*; it is the Value* that refers to all the fields of the block
std::string json_m = (*op_struct)["json_metadata"];
std::string elements = "";
if((json_m.compare("") != 0) && (json_m.compare("{}") != 0) && (json_m.compare("\"\"") != 0)){
Document js;
js.Parse<0>(json_m.c_str());
elements = elements + search_member(js, "community") + search_member(js, "tags") + search_member(js, "app");
}
Comment * comment = new Comment(title + " " + body + " " + elements, auth);
...
Проблема возникает в строке js.FindMember(member.c_str());
, в функции search_member()
, поскольку js.Parse<0>(json_m.c_str());
распознает, что вход является допустимым JSON, и действительно это действительно, это относится к:
"\"{\\\"tags\\\":[\\\"hello\\\",\\\"world\\\"],\\\"app\\\":\\\"application_for_publish_content\\\",\\\"format\\\":\\\"markdown+html\\\",\\\"pollid\\\":\\\"p_id\\\",\\\"image\\\":[\\\"https://un.useful.url/path/image.png\\\"]}\""
Но тогда результатом этого вычисления является строка:
"{\"tags\":[\"hello\",\"world\"],\"app\":\"application_for_publish_content\",\"format\":\"markdown+html\",\"pollid\":\"p_id\",\"image\"
И по этой причине функция FindMember()
не может найти ни одного поля tags
, community
или app
, поскольку оно распознается как строка.
Мой вопрос является: есть ли способ (отличается, просто пропустив этот блок), с помощью которого я могу распознать такие особые случаи?