[英]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! 在這里查看演示。
顯然,這里您將使用一個庫來為您執行此操作。 我將向您介紹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
! 參考部分下面提供了指導您完成此操作的參考。
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
直接對值進行操作, 而不以任何方式影響任何可能容器的結構(它從不影響容器的大小或存儲分配)。算法庫為各種目的(例如搜索,排序,計數,操縱)定義了對元素范圍進行操作的函數。
參考文獻:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.