c++:解析JSON字符串,关键字不包含在双引号中
C++: parsing JSON string, having keys not enclosed into double quotes
我已经成功使用卡萨布兰卡Json c++库(cppresst)一段时间了。它的解析器(web::json::value::parse(<json_string>)
)可以完美地处理有效的 JSON字符串。说这将被正确解析:
{
"key1": [["1", 0.4], ["0", 0.6]],
"key2": true,
"key3": 1,
"key4": [{"key41": 1}, {"key42": [1,2,3]}]
}
现在,我面临解析JSON对象的必要性,其关键字没有被括在双引号中:
{
key1: [[1, 0.4], [0, 0.6]],
key2: true,
key3: 1,
key4: [{key41: 1}, {key42: [1,2,3]}]
}
是否有一个很好的方法来正确解析这个,然后序列化成一个有效的JSON,这样卡萨布兰卡可以正确解析结果的有效JSON ?
Hjson似乎可以用于此目的,但它不提供c++所需的库。他们提到了C语言的jzon
库——我试过了:它只有单向解析(没有序列化),甚至解析也不能正确工作(甚至不能解析有效的json)
这可能不是最快的方法,但是如果用最少的代码行数来衡量代码的优美程度,那么它将会非常高。
你得到的是一个类似javascript的对象。让我们将其插入javascript引擎并使用它来生成适当的JSON。我将使用Qt的QJSEngine
,因为我对它相当熟悉:
constexpr char const* str = R"({
key1: [[1, 0.4], [0, 0.6]],
key2: true,
key3: 1,
key4: [{key41: 1}, {key42: [1,2,3]}]
})";
QJSEngine e;
QString script = QString("JSON.stringify(%0)").arg(str);
就可以求值了
e.evaluate(script).toString().toStdString()
收益率{"key1":[[1,0.4],[0,0.6]],"key2":true,"key3":1,"key4":[{"key41":1},{"key42":[1,2,3]}]}
这个粗糙的方法可以工作。
(未测试代码)
我们有三个状态,NEUTRAL, ONSTRING和ONALNUM。
我们从中性开始。如果我们点击"我们进入ONSTRING。如果我们点击alpha,我们进入ONALNUM。如果我们进入或离开校友,我们发出一个引号。我们还发出字符read。如果我们在ONALNUM中,当我们点击非alnum时,我们将退出它,并进入NEUTRAL,除非我们点击quote,当它是一个解析错误时。如果我们在ONSTRING中,我们应用JSON字符串转义规则,我不知道。
#define NEUTRAL 0
#define ONSTRING 1
#define ONALNUM 2
int state = NEUTRAL;
char *inptr = str;
char ch;
while( (ch = *inptr++))
{
if(state == NEUTRAL)
{
if( isalpha(ch) )
{
emit('"');
state = ONALNUM;
}
else if(ch = '"')
state = ONSTRING;
emit(ch);
}
else if(state == ONSTRING)
{
/* JSON string escape rules here */
if(ch == '"')
state = NEUTRAL;
emit(ch);
}
else if(state == ONALNUM)
{
emit(ch);
if(!isalnum(ch))
{
state = NEUTRAL;
emit('"');
}
}
}
问题
根据你的问题的上下文,你想要删除",这样你就可以有一个适当的JSON格式。
对于JSON解析部分,您应该使用库。我很快就会在这里发布一个例子。 解决方案为了做到这一点,我们将使用<algorithm>
库中的std::replace
函数;虽然我们可以自己实现这些功能,但最好还是使用标准库,因为标准库的创建者努力优化了这些函数,使其发挥最大的功能。所以,让我们把你从问题中给我们的代码,并使其适合json。
#include <algorithm>
#include <string>
#include <iostream>
using std::string;
using std::cout;
using std::endl;
void convert_char(string &s,char from_conv, char to_conv) {
std::replace( s.begin(), s.end(), from_conv, to_conv); // replace all 'x' to 'y'
}
int main()
{
string str = "{ n
"key1": [["1", 0.4], ["0", 0.6]], n
"key2": true, n
"key3": 1, n
"key4": [{"key41": 1}, {"key42": [1,2,3]}] n }";;
convert_char(str,'"',(char)0);
cout << str << endl;
}
你可以看到这里有一个叫做convert_char
的函数,它将一个字符转换为另一个字符。所以基本上就像你问的那样,我们去掉了双引号,然后,它的格式就像JSON了!看一下这里的的演示。
JSON解析器解决方案
显然,这里您将使用库来为您完成此操作。我要向大家介绍sciter
!基本上,对于sciter
,你所要做的就是:
#include <algorithm>
#include <string>
#include <iostream>
#include <sciter>
using std::string;
using std::cout;
using std::endl;
int main()
{
string str = "{ n
"key1": [["1", 0.4], ["0", 0.6]], n
"key2": true, n
"key3": 1, n
"key4": [{"key41": 1}, {"key42": [1,2,3]}] n }";;
sciter::value str_conv = sciter::value::from_string( str, CVT_JSON_LITERAL );
cout << str_conv << endl;
}
现在根据这段代码,JSON格式的代码是在str_conv
!下面的参考资料部分提供了指导您完成此操作的参考资料。
引用:
sciter
std::replace
string::replace
std::refrence_if
std::replace
:
template <class ForwardIterator, class T>
void replace (ForwardIterator first, ForwardIterator last,
const T& old_value, const T& new_value); //source cpprefrence
引用:cpprefrence
<algorithm>
:
许多主题都在算法库中。你猜对了,它是一个算法库。
头文件<algorithm>
定义了一组特别设计用于元素范围的函数。
范围是任何可以通过迭代器或指针访问的对象序列,例如数组或某些STL容器的实例。但是请注意,
algorithms
通过iterators
直接对值进行操作,不会以任何方式影响任何可能的容器的结构(它从不影响容器的大小或存储分配)。算法库为各种目的(如搜索、排序、计数、操作)定义了对元素范围进行操作的函数。
引用:
cplusplus
cpprefrence
- Visual Studio 2015:Extern "C" 和 "export" 关键字
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- C++中的"inline"关键字
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- 编译包含字符串的代码时遇到问题
- c++库的公共头文件中应该包含什么
- 如何确保C++函数在定义之前声明(如override关键字)
- 只要我不包含一个标题,重新定义C++关键字合法吗
- C++ 如何将关键字"friend"与两个类的成员函数一起使用 相互包含
- extern 关键字在包含文件头文件C++
- C++ 包含中的"未定义"模块关键字
- 如果我在标题文件中使用关键字的声明,则应该在定义本身中包含相同的关键字
- 如何在文件中搜索关键字,然后打印其中包含的字符串
- 我需要在一行中包含所有具有相同关键字的值
- 如何使用C++(g++)编译器编译包含C++关键字的C代码
- 包含一个图形节点作为关键字的无序映射
- 当已经有"struct"时,在C++中包含'class'关键字的原因是什么?
- c++:解析JSON字符串,关键字不包含在双引号中
- 头文件与源/实现文件中关键字包含C++ "Rules"
- 包含虚拟关键字和虚拟字符的类的大小