0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C++: JSON風の階層構造を実装する

0
Last updated at Posted at 2025-12-18

初めに

t["user"]["name"] = "K10-K10";
t["user"]["age"] = 15;

std::cout << t["user"]["name"] << std::endl;//K10-K10

のような階層構造を実装したい。

コード

#include <iostream>
#include <map>
#include <string>
#include <variant>

class Json {
public:
    using object = std::map<std::string, Json>;
    using value  = std::variant<std::string, object>;

    value data = object{};

    class Proxy {
        Json& ref;

    public:
        Proxy(Json& r) : ref(r) {}

        Proxy operator[](const std::string& key) {//階層化
            if (!std::holds_alternative<object>(ref.data)) {
                ref.data = object{};
            }
            auto& obj = std::get<object>(ref.data);
            return Proxy(obj[key]); // key がなければ生成される
        }

        Proxy& operator=(const std::string& v) {//代入
            ref.data = v;
            return *this;
        }

        Proxy& operator=(int v) {//代入(int)
            ref.data = std::to_string(v);
            return *this;
        }

        operator std::string() const {
            if (std::holds_alternative<std::string>(ref.data)) {
                return std::get<std::string>(ref.data);
            }
            return "[object]";
        }
    };

    Proxy operator[](const std::string& key) {
        return Proxy(*this)[key];
    }
};

使い方

int main() {
    Json t;
    t["user"]["name"] = "K10-K10";
    t["user"]["age"] = 15;

    std::cout << t["user"]["name"] << std::endl;//K10-K10
    std::cout << t["user"]["age"] << std::endl;//15
    return 0;
}

解説

dataがツリー構造になっている。

std::variant<std::string, std::map<std::string, Json>>

Jsonクラス

Jsonは1ノードを指す。

class Json {
public:
    using object = std::map<std::string, Json>;
    using value  = std::string;

    std::variant<value, object> data;

    Json() : data(object{}) {}
};
JSON C++ 側
"hello" Json{ std::string("hello") }
{} Json{ map{} }
{ "a": 1 } Json{ map{ "a" → Json{"1"} } }

階層化

t["user"]["name"] = "K10-K10"

t.data
└── map
    └── "user" : Json
        └── map
            └── "name" : Json
                └── string "K10-K10"

{
  "user": {
    "name": "K10-K10"
  }
}

t["user"]["age"] = 15を追加すると

t.data
└── map
    └── "user" : Json
        └── map
            ├── "name" : Json
            │   └── "K10-K10"
            └── "age" : Json
                └── "15"

{
  "user": {
    "name": "K10-K10",
    "age": "15"
  }
}

上のコードは

t["user"]

Proxy p1 = t.operator[]("user");

["name"]

Proxy p2 = p1.operator[]("name");

= "K10-K10

Proxy& Proxy::operator=(const std::string& value) {
    ref.data = value;
    return *this;
}

のような流れで動作している。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?