C ++:解析JSON字符串,没有用双引号括起来的键

时间:2016-10-08 02:33:48

标签: c++ json casablanca

我已成功使用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)

3 个答案:

答案 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演示。

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

cpprefrence std::replace

string::replace

cpprefrence 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