Почему is_json_object () Янссона не может распознать мою строку JSON?

Я новичок в 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 из-за строгих требований к размеру.

3

Решение

Вы всегда можете использовать существующее решение, такое как дерево свойств 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/

4

Другие решения

Для форматирования 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;
}
4

Я не знаю, какую библиотеку JSON вы используете, но вот несколько советов о том, что может быть не так.

  • size_t i не инициализируется ни к чему, а затем передается в json_array_get,
  • json_array_get передается корневой объект, который является не массивом JSON, а объектом JSON. В терминологии JSON, root["args"] будет массив.

Конечно, в зависимости от семантики вашей библиотеки JSON, ни одна из этих проблем не может быть вообще проблемой, но они кажутся мне красными флагами.

2

Касабланка (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.

2
По вопросам рекламы [email protected]