Elsaの技術日記(徒然なるままに)

主に自分で作ったアプリとかの報告・日記を記載

MENU

C++でjsonデータを取り扱う

今回はC++jsonデータを取り扱ってみたいと思います。
簡単なcsvデータ(カンマ区切りのみ)であれば文字列をparseすればよいだけなので簡単なのですが、
jsonデータってどうやればよいのだろう??
と気になったので調べてみました!!

今回は調べて動かした内容の備忘録をまとめたいと思います。



jsonデータを扱うためには?

調べてみたところ、nlohmannより公開されているライブラリを用いるのが手っ取り早いようでした。
ライセンスはMITでした。
github.com

こちらのgithub
「single_include/nlohmann/」
配下の”json.hpp”を作成しているソースコードと同階層に格納すればライブラリが使用できます。
Linuxの場合にはinclude配下に格納してもよいです。

今回はこちらのnlohmann json.hppを用いてjsonデータやファイルを取り扱っていきたいと思います!!

json型の文字列をjsonオブジェクトに変換

ではまずは文字列をjson型のオブジェクトに変換してみます。
コードはこちら。

#include <iostream>
#include "json.hpp"

void main(){
    std::string jsonstr = R"({
        "str":"こんにちは",
        "boolian":false,
        "person":[
            {
                "name":"Taro",
                "age":20
            },
            {
                "name":"Tom",
                "age":30
            }
        ]
    })";
    auto jobj = json::parse(jsonstr);
    std::cout <<"抽出: " << jobj["person"] << endl;
}

実際に文字列をオブジェクトに変換するのはこちらの1行のみ!!

auto jobj = json::parse(jsonstr);

これで変換OK!!とても簡単でした。

jsonオブジェクトから各種要素を取得する場合には、

 jobj["str"] 
 jobj["person"]

といったように指定すればOKです。

またjsonオブジェクトに値を代入することも可能です。
例えばこんな感じに。

cout << jobj["str"] << endl;   // こんにちは
jobj["str"] = "Hello";
cout << jobj["str"] << endl;   // Hello 

jsonオブジェクトを文字列に変換

今度は逆にjsonオブジェクトを文字列に変換してみます。
コードはこちら。

#include <iostream>
#include "json.hpp"

void main(){
    std::string jsonstr = R"({
        "str":"こんにちは",
        "boolian":false,
        "person":[
            {
                "name":"Taro",
                "age":20
            },
            {
                "name":"Tom",
                "age":30
            }
        ]
    })";
    auto jobj = json::parse(jsonstr);
    std::cout <<"文字列変換: " << jobj.dump() << endl;

文字列には.dump()関数を用いればよいです。
ということで、

    auto jobj = json::parse(jsonstr);
    std::cout <<"文字列変換: " << jobj.dump() << endl;

のコードにて、jsonオブジェクト変換後、オブジェクトを文字列に変換しているコードになります。

jsonファイルからjsonデータを読み出し・取り扱い

こちらのjsonオブジェクト変換コードとファイル読み出しを用いればjsonデータを簡単に取り扱うことが出来ます。
例えばjsonファイル内のデータをこちらとした時に、

{"person":{"name":"brown","age":30,"message":"Hello"}}

こちらのようなコードを作成すればファイル内のjson要素の取得が可能になります。

#include <iostream>
#include <fstream>
#include <string>
#include "json.hpp"

void main(){
    ifstream ifs("./file.json");
    std::string jsonstr;
    if(ifs.fail()){
        cout << "File Open Error" << endl;
        return -1;
    }
    while(getline(ifs, jsonstr)){
        cout<<"[Read result] "<<str<<endl;
    }
    auto jobj = json::parse(jsonstr);
    std::cout <<"抽出: " << jobj["person"] << endl;
}

ライブラリを用いることで簡単にjsonデータの取り扱いが出来ますね!!

■ビルド時のwarning対応

バージョン7以上のgcc(g++)でコンパイルを行うと、

note: parameter passing for argument of type ‘__gnu_cxx::__normal_iterator<const nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > > >’ changed in GCC 7.1

といったwarningが出てしまうかもしれません。
まぁwarningですし出ても実行には支障は出ないのですが、、、
少し気味が悪い。。恐らくGCCのバージョンが原因なんだろうけど。。
ということで理由を調査してみました!!

すでにIssueとして上げられておりました!!
https://github.com/nlohmann/json/issues/1861

やはりバージョンに起因したものだったようです。
どうやら作成されたライブラリがバージョン6以前で作成されたことが要因のようです。
バージョン7.1以降でビルドを実行している限りwarningは無視することが出来るよう。

こちらのオプションを付ければwarningが出力されなくなるので利用sるうことが勧められておりました。

-Wno-psabi -Wall -Wextra -pedantic

確かにこちらのオプションを付ければwarningは出て来なくなりました。
とりあえずこちらの方法を採用することにします。

■最後に

今回はライブラリを用いてC++jsonデータを取り扱ってみました。
C++でも簡単にjsonパースが出来るのは少し意外でした!!