C++ 用C++读取json文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32205981/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:06:53  来源:igfitidea点击:

Reading json files in C++

c++jsondictionaryjsoncpp

提问by user3515814

I'm trying to read in a JSON file. So far I have focused on using the jsoncpplibrary. However, the documentation is quite hard to understand for me. Could anyone explain in lay terms what it does?

我正在尝试读取 JSON 文件。到目前为止,我一直专注于使用该jsoncpp库。但是,文档对我来说很难理解。任何人都可以通俗地解释它的作用吗?

Say I have a people.jsonwhich looks like this:

说我有一个people.json看起来像这样的:

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

What happens when I read this in? Can I create some sort of data structure peoplewhich I can index by Annaand Benas well as ageand profession? What would be the data type of people? I thought it would be something similar to a (nested) map, but map values always have to have the same type, don't they?

当我读到这个时会发生什么?我可以建立某种形式的数据结构people,我可以指数AnnaBen以及ageprofession?的数据类型是people什么?我认为它类似于(嵌套)地图,但地图值始终必须具有相同的类型,不是吗?

I have worked with python before and my "goal" (which may be ill-set for C++) is to obtain the equivalent of a nested python dictionary.

我之前曾使用过 python,我的“目标”(对于 C++ 来说可能是错误的)是获得相当于嵌套 python 字典的东西。

采纳答案by Pooja Nilangekar

  1. Yes you can create a nested data structure peoplewhich can be indexed by Annaand Ben. However, you can't index it directly by ageand profession(I will get to this part in the code).

  2. The data type of peopleis of type Json::Value(which is defined in jsoncpp). You are right, it is similar to the nested map, but Valueis a data structure which is defined such that multiple types can be stored and accessed. It is similar to a map with a stringas the key and Json::Valueas the value. It could also be a map between an unsigned intas key and Json::Valueas the value (In case of json arrays).

  1. 是的,您可以创建一个people可以由Anna和索引的嵌套数据结构Ben。但是,您不能直接通过ageand 对其进行索引profession(我将在代码中介绍这一部分)。

  2. 的数据类型people是类型Json::Value(在 jsoncpp 中定义)。你是对的,它类似于嵌套映射,但它Value是一种数据结构,它被定义为可以存储和访问多种类型。它类似于以 astring作为键和Json::Value作为值的映射。它也可以是unsigned intas 键和Json::Value作为值之间的映射(如果是 json 数组)。

Here's the code:

这是代码:

#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.

As you can see, you can index the json object only based on the hierarchy of the input data.

如您所见,您只能根据输入数据的层次结构对 json 对象进行索引。

回答by Arsen

Have a look at nlohmann's JSON Repository on GitHub. I have found that it is the most convenient way to work with JSON.

在 GitHub 上查看nlohmann 的 JSON 存储库。我发现这是使用 JSON 最方便的方式。

It is designed to behave just like an STL container, which makes its usage very intuitive.

它的设计行为就像一个 STL 容器,这使得它的使用非常直观。

回答by Malcolm McLean

Essentially javascript and C++ work on two different principles. Javascript creates an "associative array" or hash table, which matches a string key, which is the field name, to a value. C++ lays out structures in memory, so the first 4 bytes are an integer, which is an age, then maybe we have a fixed-wth 32 byte string which represents the "profession".

基本上 javascript 和 C++ 工作在两个不同的原则上。Javascript 创建一个“关联数组”或哈希表,它将字符串键(字段名称)与值匹配。C++ 在内存中布置结构,所以前 4 个字节是一个整数,这是一个年龄,然后也许我们有一个固定的 32 字节字符串代表“职业”。

So javascript will handle things like "age" being 18 in one record and "nineteen" in another. C++ can't. (However C++ is much faster).

因此,javascript 将处理诸如“年龄”在一个记录中为 18 岁而在另一个记录中为“十九岁”之类的问题。C++ 不能。(但是 C++ 快得多)。

So if we want to handle JSON in C++, we have to build the associative array from the ground up. Then we have to tag the values with their types. Is it an integer, a real value (probably return as "double"), boolean, a string? It follows that a JSON C++ class is quite a large chunk of code. Effectively what we are doing is implementing a bit of the javascript engine in C++. We then pass our JSON parser the JSON as a string, and it tokenises it, and gives us functions to query the JSON from C++.

所以如果我们想在 C++ 中处理 JSON,我们必须从头开始构建关联数组。然后我们必须用它们的类型标记这些值。它是整数、实数值(可能返回为“double”)、布尔值还是字符串?因此,JSON C++ 类是相当大的代码块。实际上,我们正在做的是用 C++ 实现一些 javascript 引擎。然后我们将 JSON 作为字符串传递给我们的 JSON 解析器,它对它进行标记,并为我们提供从 C++ 查询 JSON 的函数。

回答by Sandesh Kumar Sodhi

Example (with complete source code) to read a json configuration file:

读取json配置文件的示例(含完整源代码):

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

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
 > 

回答by LaLa

Here is another easier possibility to read in a json file:

这是在 json 文件中读取的另一种更简单的可能性:

#include "json/json.h"

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

You can then get the values like this:

然后你可以得到这样的值:

cout << root["key"]

回答by ChauhanTs

You can use c++ boost::property_tree::ptree for parsing json data. here is the example for your json data. this would be more easy if you shift name inside each child nodes

您可以使用 c++ boost::property_tree::ptree 来解析 json 数据。这是您的 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";
    }  
}

回答by christian audebert

storing peoples like this

像这样存储人们

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

will cause problems, particularly if differents peoples have same name..

会引起问题,特别是如果不同的人有相同的名字..

rather use array storing objects like this

而是使用数组存储这样的对象

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

like this, you can enumerates objects, or acces objects by numerical index. remember that json is storage structure, not dynamically sorter or indexer. use data stored in json to build indexes as you need and acces data.

像这样,您可以枚举对象,或通过数字索引访问对象。请记住,json 是存储结构,而不是动态排序器或索引器。使用存储在 json 中的数据根据​​需要构建索引并访问数据。