簡體   English   中英

C ++:解析JSON字符串,具有未包含在雙引號中的鍵

[英]C++: parsing JSON string, having keys not enclosed into double quotes

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

這可能不是最快的方法,但是如果用最少的代碼行來衡量優美程度,那么結果會很高。

您擁有的是一個類似於javascript的對象。 讓我們將其插入JavaScript引擎,並使用它吐出適當的JSON。 我會很熟悉Qt,因此將使用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]}]}

此粗略方法將起作用。

(未經測試的代碼)

我們有三種狀態,中性,ONSTRING和ONALNUM。

我們從中立開始。 如果我們打'“',我們進入ONSTRING。如果我們打alpha,我們進入ONALNUM。如果我們進入或離開alnum,我們發出一個引號。我們也發出字符read。如果我們在ONALNUM中,我們得到當我們遇到非數字時,除非遇到引號,否則它將進入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('\"');
       }
    }
 }

問題

從問題的上下文看來,您希望刪除“”,以便可以使用適當的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的函數,該函數將某個字符轉換為另一個字符。 因此,基本上,按照您的問題,我們刪除了雙引號和tada,其格式類似於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

cpprefrence std::replace

string::replace

cpprefrence std::refrence_if 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM