2017-10-12 88 views
0

轉換string strjsonconst char* json,當interate,顯示 失敗:(IsObject()),功能FindMember,失敗了,我不明白爲什麼這顯示出,我覺得這個json對象是正確的格式。將字符串轉換爲const * json後,當放置json對象時,顯示失敗:(IsObject()),如何解決這個問題?

// 
// main.cpp 
// rapid 
// 
// Created by Shi Yan on 10/7/17. 
// Copyright © 2017 Shi Yan. All rights reserved. 
// 

#include <iostream> 
#include "rapidjson.h" 
#include "document.h" 
#include <fstream> 
using namespace std; 
using namespace rapidjson; 
void readjson(){ 
    ifstream handle("meta_Books.json"); 
    if(handle.is_open()){ 
     //cout<<"open success"<<endl; 
     const char* json; 
     string strjson; 
     int i=1; 
     while(getline(handle,strjson)){ 
      if(i>4) 
       break; 
      cout<<strjson<<endl; 
      cout<<strjson.length()<<endl; 
      i++;    
      json=strjson.c_str(); 
      cout<<"*********************"<<endl; 
      cout<<*json<<endl; 
      StringStream s (json); 
      Document document; 
      document.ParseStream(s); 
      Value::ConstMemberIterator itr = document.FindMember("asin"); 
      cout<<itr->name.GetString()<<" = "<< itr->value.GetString()<<endl; 
     } 
    } 
} 
int main() { 
    readjson(); 
    return 0; 
} 

我認爲json對象的格式,爲什麼失敗?

image

正如你所看到的,getline()方法效果很好,因爲串的輸出是一個完整的字符串

image

+1

注意,此線'COUT << * JSON << ENDL;'正在輸出char數組中的單個字符(通過取消引用'const char *'得到'char') –

+0

但是在前兩個輸出中,我得到正確答案來查詢key =「asin」的值,但是,在處理第三個對象,它失敗了。解析第二個對象是正常的,所以我認爲不用用一個對象開始就沒有它的根。但爲什麼解析失敗? – shiyan

+0

我已經知道爲什麼要得到第一個字符,謝謝史蒂夫 – shiyan

回答

2

的斷言錯誤意味着FindMember()被稱爲上Value這並不代表JSON對象(IsObject()爲false)。

由於您顯示的代碼中只有1 FindMember(),這意味着document.FindMember()失敗時document.IsObject()爲false。您正在解析的JSON不是以其根目標中的對象開始,或者解析失敗。您在代碼中沒有測試哪種條件。

如果我不得不猜測(並且請不要讓人猜測!),失敗的JSON文檔可能包含未編碼的換行符(這在JSON字符串值內不是非法的)。這會導致std::getline()過早退出,從而導致解析問題。 您顯示的第一張截圖支持這一結論,表明strjson在發生錯誤時正在兩條單獨的「行」之間進行分割。

比使用std::getline()行由行讀取文件,嵌入式換行符冒着錯誤相反,我建議您嘗試使用RapidJSON的BasicIStreamWrapper類讀取文件文件逐文件來代替。 ParseStream()具有kParseStopWhenDoneFlag標記允許從單個輸入流解析多個根文件:

kParseStopWhenDoneFlag 

After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.

例如:

#include <iostream> 
#include <fstream> 
#include "rapidjson.h" 
#include "document.h" 
#include "istreamwrapper.h" 

using namespace std; 
using namespace rapidjson; 

void readjson() 
{ 
    ifstream handle("meta_Books.json"); 
    if (!handle.is_open()) 
    { 
     // handle error... 
     cout << "error opening file" << endl; 
    } 
    else 
    { 
     BasicIStreamWrapper<ifstream> s(handle); 
     for(int i = 1; i <= 4; ++i) 
     { 
      Document document; 
      ParseResult pr = document.ParseStream<kParseStopWhenDoneFlag>(s); 
      if (!pr) 
      { 
       // handle error... 
       cout << "error parsing document " << i << endl; 
      } 
      else if (!document.IsObject()) 
      { 
       cout << "document " << i << " is not an object" << endl; 
      } 
      else 
      { 
       Value::ConstMemberIterator itr = document.FindMember("asin"); 
       if (itr != document.MemberEnd()) 
        cout << "asin = " << itr->value.GetString() << endl; 
       else 
        cout << "asin not found" << endl; 
      } 
     } 
    } 
} 

int main() 
{ 
    readjson(); 
    return 0; 
} 
+0

我試過了,它仍然無法工作, 錯誤:使用類模板'BasicIStreamWrapper'需要模板參數BasicIStreamWrapper(handle); – shiyan

相關問題