我是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"
}
]
}
我陷入第一阶段解析这个问题。我已经将字符串转换为char,然后尝试使用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
我做错了什么以及如何正确格式化?最终我需要迭代一个数组,但无法通过它。我确定这只是初学者的错误。
-EDIT-
由于严格的尺寸要求,试图避免使用Boost。
答案 0 :(得分:4)
您可以随时使用现有的解决方案,例如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树中提取信息,可以这样做,其中type是您要提取的数据的类型,insert.key.path.here是您的密钥的路径,每个父键由句点分隔。
jsonfile.get<type>(insert.key.path.here);
另外,我不相信你在那里的JSON字符串是有效的。你很好地删除了JSON字符串本身的多余部分,但我相信这里有一个问题:
"connection" : true,
您可以在此处检查JSON字符串的有效性:http://jsonformatter.curiousconcept.com/
答案 1 :(得分:4)
对于JSON格式化,我通过C ++搜索了一个漂亮的打印解决方案无济于事。最后,我发现了一些我最终转换为C ++的java代码。尝试以下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;
}
答案 2 :(得分:2)
我不熟悉您正在使用的任何JSON库,但这里有一些关于可能出错的建议。
size_t i
未初始化为任何内容,然后传递到json_array_get
。json_array_get
传递根对象,该对象不是JSON数组,而是JSON对象。在JSON术语中,root["args"]
将是数组。当然,根据你的JSON库的语义,这根本不是问题,但它们对我来说似乎是红旗。
答案 3 :(得分:2)
Casablanca (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。