web-dev-qa-db-ja.com

C ++でJSONファイルを読み取る

JSONファイルを読み取ろうとしています。これまで、jsoncppライブラリーの使用に焦点を当ててきました。ただし、ドキュメントを理解するのは非常に困難です。誰もがそれが何をするかを簡単に説明できますか?

たとえば、people.jsonこれは次のようになります。

{"Anna" : { 
      "age": 18,
      "profession": "student"},
 "Ben" : {
      "age" : "nineteen",
      "profession": "mechanic"}
 }

これを読んだらどうなりますか? peopleAnnaおよびBenageでインデックスを作成できる、何らかのデータ構造professionを作成できますか? peopleのデータ型は何ですか? (ネストされた)マップに似たものになると思いましたが、マップ値は常に同じタイプでなければなりませんよね?

私は以前にpythonで作業しましたが、私の目標は(C++にとっては不適当かもしれません)は、入れ子になったpython辞書と同等のものを取得することです。

18
user3515814
  1. はい、peopleAnnaでインデックス付けできるネストされたデータ構造Benを作成できます。ただし、ageprofessionで直接インデックスを作成することはできません(コードのこの部分に進みます)。

  2. peopleのデータ型はJson::Value型(jsoncppで定義されています)です。ネストされたマップに似ていますが、Valueは、複数のタイプを格納およびアクセスできるように定義されたデータ構造です。これは、キーとしてstringと値としてJson::Valueを持つマップに似ています。キーとしてunsigned intと値としてJson::Valueの間のマップにすることもできます(json配列の場合)。

コードは次のとおりです。

#include <json/value.h>
#include <fstream>

std::ifstream people_file("people.json", std::ifstream::binary);
people_file >> people;

cout<<people; //This will print the entire json object.

//The following lines will let you access the indexed objects.
cout<<people["Anna"]; //Prints the value for "Anna"
cout<<people["ben"]; //Prints the value for "Ben"
cout<<people["Anna"]["profession"]; //Prints the value corresponding to "profession" in the json for "Anna"

cout<<people["profession"]; //NULL! There is no element with key "profession". Hence a new empty element will be created.

ご覧のとおり、入力データの階層に基づいてのみjsonオブジェクトにインデックスを付けることができます。

11

GitHub上のnlohmannのJSONリポジトリ をご覧ください。 JSONを使用する最も便利な方法であることがわかりました。

STLコンテナのように動作するように設計されているため、使用方法が非常に直感的です。

8
Arsen

基本的に、javascriptとC++は2つの異なる原則で機能します。 JavaScriptは、フィールド名である文字列キーを値に一致させる「連想配列」またはハッシュテーブルを作成します。 C++はメモリ内の構造をレイアウトするため、最初の4バイトは整数であり、これは年齢です。その後、「職業」を表す32バイトの固定長文字列があります。

そのため、javascriptは、あるレコードでは18歳、別のレコードでは「19歳」のようなものを処理します。 C++ではできません。 (ただし、C++ははるかに高速です)。

したがって、C++でJSONを処理する場合は、連想配列をゼロから構築する必要があります。次に、値にタイプをタグ付けする必要があります。整数、実際の値(おそらく「double」として返される)、ブール値、文字列ですか? JSON C++クラスは非常に大きなコードの塊であるということです。事実上、私たちがしていることは、C++でJavaScriptエンジンを少し実装することです。次に、JSONパーサーにJSONを文字列として渡し、トークン化して、C++からJSONを照会する関数を提供します。

2
Malcolm McLean

JSONファイルを読み込むもう1つの簡単な方法は次のとおりです。

#include "json/json.h"

std::ifstream file_input("input.json");
Json::Reader reader;
Json::Value root;
reader.parse(file_input, root);
cout << root;

その後、次のような値を取得できます。

cout << root["key"]
1
LaLa

Json構成ファイルを読み取る例(完全なソースコードを使用):

https://github.com/sksodhi/CodeNuggets/tree/master/json/config_read

 > pwd
/root/CodeNuggets/json/config_read
 > ls
Makefile  README.md  ReadJsonCfg.cpp  cfg.json
 > cat cfg.json 
{
   "Note" : "This is a cofiguration file",
   "Config" : { 
       "server-ip"     : "10.10.10.20",
       "server-port"   : "5555",
       "buffer-length" : 5000
   }   
}
 > cat ReadJsonCfg.cpp 
#include <iostream>
#include <json/value.h>
#include <jsoncpp/json/json.h>
#include <fstream>

void 
displayCfg(const Json::Value &cfg_root);

int
main()
{
    Json::Reader reader;
    Json::Value cfg_root;
    std::ifstream cfgfile("cfg.json");
    cfgfile >> cfg_root;

    std::cout << "______ cfg_root : start ______" << std::endl;
    std::cout << cfg_root << std::endl;
    std::cout << "______ cfg_root : end ________" << std::endl;

    displayCfg(cfg_root);
}       

void 
displayCfg(const Json::Value &cfg_root)
{
    std::string serverIP = cfg_root["Config"]["server-ip"].asString();
    std::string serverPort = cfg_root["Config"]["server-port"].asString();
    unsigned int bufferLen = cfg_root["Config"]["buffer-length"].asUInt();

    std::cout << "______ Configuration ______" << std::endl;
    std::cout << "server-ip     :" << serverIP << std::endl;
    std::cout << "server-port   :" << serverPort << std::endl;
    std::cout << "buffer-length :" << bufferLen<< std::endl;
}
 > cat Makefile 
CXX = g++
PROG = readjsoncfg

CXXFLAGS += -g -O0 -std=c++11

CPPFLAGS += \
        -I. \
        -I/usr/include/jsoncpp

LDLIBS = \
                 -ljsoncpp

LDFLAGS += -L/usr/local/lib $(LDLIBS)

all: $(PROG)
        @echo $(PROG) compilation success!

SRCS = \
        ReadJsonCfg.cpp
OBJS=$(subst .cc,.o, $(subst .cpp,.o, $(SRCS)))

$(PROG): $(OBJS)
        $(CXX) $^ $(LDFLAGS) -o $@

clean:
        rm -f $(OBJS) $(PROG) ./.depend

depend: .depend

.depend: $(SRCS)
        rm -f ./.depend
        $(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $^ >  ./.depend;

include .depend
 > make
Makefile:43: .depend: No such file or directory
rm -f ./.depend
g++ -g -O0 -std=c++11 -I. -I/usr/include/jsoncpp -MM ReadJsonCfg.cpp >  ./.depend;
g++ -g -O0 -std=c++11 -I. -I/usr/include/jsoncpp  -c -o ReadJsonCfg.o ReadJsonCfg.cpp
g++ ReadJsonCfg.o -L/usr/local/lib -ljsoncpp -o readjsoncfg
readjsoncfg compilation success!
 > ./readjsoncfg 
______ cfg_root : start ______
{
        "Config" : 
        {
                "buffer-length" : 5000,
                "server-ip" : "10.10.10.20",
                "server-port" : "5555"
        },
        "Note" : "This is a cofiguration file"
}
______ cfg_root : end ________
______ Configuration ______
server-ip     :10.10.10.20
server-port   :5555
buffer-length :5000
 > 
1

このような人々を保管する

{"Anna" : { 
  "age": 18,
  "profession": "student"},
"Ben" : {
  "age" : "nineteen",
  "profession": "mechanic"}
 }

特に異なる人々が同じ名前を持っている場合、問題が発生します。

むしろこのようなオブジェクトを格納する配列を使用してください

{
  "peoples":[
       { 
           "name":"Anna",  
           "age": 18,
           "profession": "student"
       },
       {
           "name":"Ben",
           "age" : "nineteen",
           "profession": "mechanic"
       } 
  ]
}

このように、オブジェクトを列挙したり、数値インデックスでオブジェクトにアクセスしたりできます。 jsonはストレージ構造であり、動的なソーターやインデクサーではないことに注意してください。 jsonに保存されたデータを使用して、必要に応じてインデックスを作成し、データにアクセスします。

0

JSONデータの解析にc ++ boost :: property_tree :: ptreeを使用できます。 JSONデータの例を次に示します。これは、各子ノード内で名前をシフトするとより簡単になります

#include <iostream>                                                             
#include <string>                                                               
#include <Tuple>                                                                

#include <boost/property_tree/ptree.hpp>                                        
#include <boost/property_tree/json_parser.hpp> 
 int main () {

    namespace pt = boost::property_tree;                                        
    pt::ptree loadPtreeRoot;                                                    

    pt::read_json("example.json", loadPtreeRoot);                               
    std::vector<std::Tuple<std::string, std::string, std::string>> people;      

    pt::ptree temp ;                                                            
    pt::ptree tage ;                                                            
    pt::ptree tprofession ;                                                     

    std::string age ;                                                           
    std::string profession ;                                                    
    //Get first child                                                           
    temp = loadPtreeRoot.get_child("Anna");                                     
    tage = temp.get_child("age");                                               
    tprofession = temp.get_child("profession");                                 

    age =  tage.get_value<std::string>();                                       
    profession =  tprofession.get_value<std::string>();                         
    std::cout << "age: " << age << "\n" << "profession :" << profession << "\n" ;
    //Push Tuple to vector                                                      
    people.Push_back(std::make_Tuple("Anna", age, profession));                 

    //Get Second child                                                          
    temp = loadPtreeRoot.get_child("Ben");                                      
    tage = temp.get_child("age");                                               
    tprofession = temp.get_child("profession");                                 

    age =  tage.get_value<std::string>();                                       
    profession  =  tprofession.get_value<std::string>();                        
    std::cout << "age: " << age << "\n" << "profession :" << profession << "\n" ;
    //Push Tuple to vector                                                      
    people.Push_back(std::make_Tuple("Ben", age, profession));                  

    for (const auto& tmppeople: people) {                                       
        std::cout << "Child[" << std::get<0>(tmppeople) << "] = " << "  age : " 
        << std::get<1>(tmppeople) << "\n    profession : " << std::get<2>(tmppeople) << "\n";
    }  
}
0
ChauhanTs