Я новичок в C ++ и не могу понять, как вырезать некоторые разные данные из строки, а затем проанализировать его как JSON.
В итоге я использовал самый документированный анализатор JSON, который только мог найти — jansson. Кажется, отлично, хотя я застрял на первом препятствии.
Моя программа получает строку в следующем формате:
5::/chat:{"name":"steve","args":[{"connection":"true"}, { "chatbody" : "I am the body" }]}
Я удалил все, что находится вне фигурных скобок:
std::string str=message;
unsigned pos = str.find("{");
std::string string = str.substr (pos);
Это оставляет:
{
"name": "steve",
"args": [
{
"connection": "true"},
{
"chatbody": "I am the body"}
]
}
Я застрял на первом этапе разбора этого. Я преобразовал строку в символ, а затем попытался использовать json_loads, но ничего полезного не получаю …
Все выглядит так:
void processJson(string message)
{
json_t *root;
json_error_t error;
size_t i;
std::string str=message;
unsigned pos = str.find("{");
std::string str3 = str.substr (pos);
const char * c = str.c_str();
json_t *data, *sha, *name;
root = json_loads(c, 0, &error);
data = json_array_get(root, i);
cout << data;
if(!json_is_object(root))
{
fprintf(stderr, "error: commit data %d is not an object\n", i + 1);
}
}
Мне нужно вывести значения, но я просто получаю 01, 02, 03 ….
is_json_object просто говорит:
error: commit data 1068826 is not an object
error: commit data 1068825 is not an object
error: commit data 1068822 is not an object
Что я делаю не так и как мне правильно отформатировать это? В конечном счете мне нужно будет перебрать массив, но я не могу обойти это. Я уверен, что это просто ошибка новичка.
-РЕДАКТИРОВАТЬ-
Попытка избежать использования Boost из-за строгих требований к размеру.
Вы всегда можете использовать существующее решение, такое как дерево свойств Boost, в котором есть функция автоматического разбора файлов JSON. Это буквально так же просто, как добавить эти два заголовка:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
И затем добавление этого небольшого фрагмента кода, где jsonfile, очевидно, означает ваше имя файла.
boost::property_tree::ptree jsontree;
boost::property_tree::read_json(jsonfile, jsontree);
Если вы когда-нибудь захотите извлечь информацию из вашего дерева JSON, вы можете сделать это следующим образом, где тип — это тип данных, которые вы хотите извлечь, а insert.key.path.here — путь к вашему ключу с каждым родителем. Ключ разделен точками.
jsonfile.get<type>(insert.key.path.here);
Кроме того, я не верю, что имеющаяся у вас строка JSON является действительной. Вы хорошо удалили лишнюю строку вокруг самой строки JSON, но я считаю, что здесь есть проблема:
"connection" : true,
Вы можете проверить правильность вашей строки JSON здесь: http://jsonformatter.curiousconcept.com/
Для форматирования JSON я искал красивое решение для печати через C ++, но безрезультатно. Наконец, я нашел некоторый код Java, который в конечном итоге преобразовал в C ++. Попробуйте следующее для форматирования JSON:
std::string formattedJson(char *json)
{
std::string pretty;
if (json == NULL || strlen(json) == 0)
{
return pretty;
}
std::string str = std::string(json);
bool quoted = false;
bool escaped = false;
std::string INDENT = " ";
int indent = 0;
int length = (int) str.length();
int i;
for (i = 0 ; i < length ; i++)
{
char ch = str[i];
switch (ch)
{
case '{':
case '[':
pretty += ch;
if (!quoted)
{
pretty += "\n";
if (!(str[i+1] == '}' || str[i+1] == ']'))
{
++indent;
for (int j = 0 ; j < indent ; j++)
{
pretty += INDENT;
}
}
}
break;
case '}':
case ']':
if (!quoted)
{
if ((i > 0) && (!(str[i-1] == '{' || str[i-1] == '[')))
{
pretty += "\n";
--indent;
for (int j = 0 ; j < indent ; j++)
{
pretty += INDENT;
}
}
else if ((i > 0) && ((str[i-1] == '[' && ch == ']') || (str[i-1] == '{' && ch == '}')))
{
for (int j = 0 ; j < indent ; j++)
{
pretty += INDENT;
}
}
}
pretty += ch;
break;
case '"':
pretty += ch;
escaped = false;
if (i > 0 && str[i-1] == '\\')
{
escaped = !escaped;
}
if (!escaped)
{
quoted = !quoted;
}
break;
case ',':
pretty += ch;
if (!quoted)
{
pretty += "\n";
for (int j = 0 ; j < indent ; j++)
{
pretty += INDENT;
}
}
break;
case ':':
pretty += ch;
if (!quoted)
{
pretty += " ";
}
break;
default:
pretty += ch;
break;
}
}
return pretty;
}
Я не знаю, какую библиотеку JSON вы используете, но вот несколько советов о том, что может быть не так.
size_t i
не инициализируется ни к чему, а затем передается в json_array_get
,json_array_get
передается корневой объект, который является не массивом JSON, а объектом JSON. В терминологии JSON, root["args"]
будет массив.Конечно, в зависимости от семантики вашей библиотеки JSON, ни одна из этих проблем не может быть вообще проблемой, но они кажутся мне красными флагами.
Касабланка (REST C ++ SDK) имеет довольно хороший анализатор JSON, который вы можете использовать, даже если вы не используете функциональность HTTP.
Вы можете извлечь файлы анализатора JSON в статическую библиотеку и связать ее с существующим проектом. Файлы для извлечения:
src\json\json.cpp
src\json\json_parsing.cpp
src\json\json_serialization.cpp
src\utilities\asyncrt_utils.cpp
include\cpprest\json.h
include\cpprest\xxpublic.h
include\cpprest\basic_types.h
include\cpprest\asyncrt_utils.h
Я могу подтвердить, что это работает, поскольку я недавно использовал это как статическую библиотеку для своих проектов.
Я также пытался использовать Jansson, но парсер в Касабланке просто удобнее в использовании и имеет лучшую поддержку Unicode.