我已成功使用Casablanca Json C ++库(cpprest)一段时间了。它的解析器(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,以便Casablanca可以正确解析结果有效的JSON?
Hjson似乎可以用于此目的,但它不提供C ++所需的库。他们为C提到了jzon
库 - 我尝试了它:它只有单向解析(没有序列化),甚至解析也不能正常工作(甚至无法解析有效的JSON)
答案 0 :(得分:1)
这可能不是最快的方法,但如果用最少的代码行测量好看,它会很高。
你拥有的是类似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]}]}
答案 1 :(得分:0)
这种原始方法可行。
(未经测试的代码)
我们有三个状态,中性,ONSTRING和ONALNUM。
我们从中性开始。如果我们点击'“'我们进入ONSTRING。如果我们点击alpha我们进入ONALNUM。如果我们进入或退出alnum,我们发出一个引号。我们也发出字符读取。 如果我们在ONALNUM中,当我们击中非alnum时,我们会离开它,amd进入NEUTRAL,除非我们点击引号,当它是解析错误时。如果我们在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('\"');
}
}
}
答案 2 :(得分:-1)
在你的问题的背景下,你似乎想要&#34;&#34;已删除,因此您可以使用正确的JSON格式。
对于JSON解析部分,您应该使用库。我很快就会在这里发布一个例子。
为了做到这一点,我们将使用std::replace
库中的<algorithm>
函数;虽然我们可以自己实现这一点,但最好使用标准库,因为他们的创建者努力将这些功能优化到最全面的功能。因此,让我们从问题中提取您提供给我们的代码并使其适合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
的函数,它将某个字符转换为另一个字符。所以基本上你的问题我们删除了双引号和tada,它的格式就像JSON!看一下here演示。
显然,在这里你将使用一个库来为你做这件事。我要向你介绍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
!引用您的参考资料如下所示。
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
直接对值进行操作,不影响以任何方式对任何可能容器的结构进行操作(它永远不会影响其大小或存储分配)容器)。算法库定义了各种用途的函数(例如搜索,排序,计数,操作),这些函数在元素范围内运行。
参考文献: