用C ++读取json文件

时间:2015-08-25 13:55:34

标签: c++ json dictionary jsoncpp

我试图读取JSON文件。到目前为止,我一直专注于使用jsoncpp库。但是,我很难理解文档。任何人都可以用非专业术语解释它的作用吗?

说我有people.json,如下所示:

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

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

之前我曾经使用过python和我的目标" (可能是C ++的错误设置)是获得等效的嵌套python字典。

8 个答案:

答案 0 :(得分:9)

  1. 是的,您可以创建一个嵌套数据结构people,可以AnnaBen编制索引。但是,您无法通过ageprofession直接对其进行索引(我将在代码中介绍此部分)。

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

  3. 以下是代码:

    #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对象。

答案 1 :(得分:6)

看看nlohmann's JSON Repository on GitHub。我发现这是使用JSON最方便的方法。

它的设计就像STL容器一样,使得它的使用非常直观。

答案 2 :(得分:2)

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

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

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

答案 3 :(得分:1)

读取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
 > 

答案 4 :(得分:1)

这是另一个更容易读取json文件的可能性:

#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"]

答案 5 :(得分:1)

fedora 33 的完整最小工作示例

使用 sudo dnf install jsoncpp-devel 获取图书馆。

将以下文件存储在您的项目文件夹中:

people.json

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

ma​​in.cpp

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

int main()
{
    Json::Value people;
    std::ifstream people_file("people.json", std::ifstream::binary);
    people_file >> people;

    std::cout << people["Anna"] << "\n";
    std::cout << people["Anna"]["profession"] << "\n";
}

使用 g++ -ljsoncpp main.cpp 编译。调用 ./a.out 会产生

输出

{
    "age" : 18,
    "profession" : "student"
}
"student"

答案 6 :(得分:0)

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.

答案 7 :(得分:0)

您可以使用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";
    }  
}