在C++中阅读json文件

wmomyfyw  于 2023-01-03  发布在  其他
关注(0)|答案(8)|浏览(189)

我正在尝试读入一个JSON文件。到目前为止,我一直专注于使用jsoncpp库。然而,文档对我来说很难理解。有人能用通俗的术语解释一下它的作用吗?
假设我有一个people.json,如下所示:

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

当我读到这个的时候会发生什么?我可以创建某种数据结构people,我可以通过AnnaBen以及ageprofession来索引它吗?people的数据类型是什么?我认为它类似于(嵌套的)map,但是map值总是必须具有相同的类型,不是吗?
我以前使用过python,我的“目标”(对于C++来说可能是病态的)是获得一个嵌套python字典的等价物。

dwthyt8l

dwthyt8l1#

1.可以创建嵌套数据结构people,它可以通过AnnaBen索引,但是不能直接通过ageprofession索引(我将在代码中介绍这一部分)。

  1. people的数据类型为Json::Value(在jsoncpp中定义).你是对的,它类似于嵌套Map,但是Value是定义为可以存储和访问多种类型的数据结构,类似于以string为键、以Json::Value为值的Map。它也可以是作为键的unsigned int和作为值的Json::Value之间的Map(在json数组的情况下)。
    下面是代码:
//if include <json/value.h> line fails (latest kernels), try also:
//  #include <jsoncpp/json/json.h>
#include <json/value.h>
#include <fstream>

std::ifstream people_file("people.json", std::ifstream::binary);
Json::Value people;
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对象。

xfb7svmp

xfb7svmp2#

看看nlohmann's JSON Repository on GitHub,我发现它是使用JSON最方便的方法。
它被设计成像STL容器一样工作,这使得它的使用非常直观。

66bbxpm5

66bbxpm53#

基本上,javascript和C的工作原理是不同的。Javascript创建了一个“关联数组”或哈希表,它匹配一个字符串键(字段名)和一个值。C在内存中布局结构,所以前4个字节是一个整数,这是一个年龄,然后我们可能有一个固定长度的32字节字符串来表示“职业”。
所以javascript可以处理诸如“age”在一个记录中是18而在另一个记录中是“ninteen”这样的事情,而C不能(然而C要快得多)。
因此,如果我们想在C中处理JSON,我们必须从头开始构建关联数组,然后我们必须用类型标记值,它是整数还是真实的数值(可能返回为“double”)、布尔值、一个字符串?由此可见,一个JSON C类是相当大的一块代码。实际上,我们所做的是在C中实现一点JavaScript引擎。然后,我们将JSON作为字符串传递给JSON解析器,解析器将其标记化,并为我们提供从C查询JSON的函数。

abithluo

abithluo4#

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

yh2wf1be5#

fedora 33的完整最小工作示例

使用sudo dnf install jsoncpp-devel获取库。
将以下文件存储在项目文件夹中:

    • 人民. json**
{
    "Anna":
    { 
        "age": 18,
            "profession": "student"
        },
    "Ben":
    {
        "age" : "nineteen",
        "profession": "mechanic"
    }
}
    • 主. 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"
agyaoht7

agyaoht76#

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

44u64gxh7#

下面是另一种更容易读入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"]
lymnna71

lymnna718#

储存这样的人

{"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中的数据来根据你的需要建立索引并访问数据。

相关问题