LoginSignup
7
2

More than 5 years have passed since last update.

ofxJsonUtilsというaddon

Last updated at Posted at 2016-09-05

手前味噌ですが, 最近ofxJsonUtilsというaddonを書いてまして, それの紹介.

ofxJsonUtilsとは

今後ofxXmlSettingが無くなってofXmlになりそうなのですがこれがまた非常に使いづらい.
そもそもXMLの閉じタグが嫌いだしjs大好き勢としてはjson最高って言いたい.
でもofのaddonでjsonの決定打がなかなか出ないのですが, 多分0.10.0からnlohmann/jsonというC++11なモダンなjsonライブラリがusing ofJson = nlohmann::json; として使えるようになります.

で, それを先取りしてofxJsonUtilsというのを書いてまして, nlohmann::jsonが無い場合はofJsonとして読み込んでしまったりとかして今後も互換性を保てるjson使いが出来る, と.

そんで, nlohmann::json はなかなかイケてるんですが痒いところに手が届かないのでラッパーライブラリ的なのも書いている状況です.

ofxJsonUtils::loadFromFile

毎回ファイルからテキスト読み込んでパースしてっていう数行のことですが, 大体定型文なので関数にしてます.

  ofJson json = ofxJsonUtils::loadFromFile("hoge.json");

toJson, loadJson

例えば,

struct my_struct {
  ofVec3f point;
  int radius;
};

のようなクラス/構造体をjsonにシリアライズしたい場合に

struct my_struct {
  ofVec3f point;
  int radius;
  ofJson toJson() const {
    ofJson json;
    json["point"] = ofxJsonUtils::convert(point);
    json["raidus"] = radius;
    return json;
  }
  void loadJson(const ofJson &json) {
    ofxJsonUtils::parse(json["point"], point);
    ofxJsonUtils::parse(json["radius"], radius);
  }
};

toJson, loadJson を定義しておくと今度は

struct other_struct {
  std::vector<my_struct> objs;
  ofJson toJson() const {
    ofJson json;
    json["objs"] = ofxJsonUtils::convert(objs);
    return json;
  };
  void loadJson(const ofJson &json) {
    ofxJsonUtils::parse(json["objs"], objs);
  }
};

と再帰的に使っていくことが出来ます.

既に存在する自分が手を入れれないクラスに関しても


struct not_my_struct { ... };

ofJson convert(const not_my_struct &value) {
  return {
    {"x", value.x},
    {"y", value.y}
  };
}

void parse(const ofJson &json, not_my_struct &value) {
  value.x = json["x"];
  value.y = json["y"];
}

と関数を定義することで外部からでも対応させることが出来ます.

ofxJsonify

また, ofxJsonify というtemplateクラスを使うと

  struct other_struct : public ofxJsonify<other_struct> {
    std::vector<my_struct> objs;
    ofJson toJson() const {
      ofJson json;
      json["objs"] = ofxJsonUtils::convert(objs);
      return json;
    };
    void loadJson(const ofJson &json) {
      ofxJsonUtils::parse(json["objs"], objs);
    }
  }

とするだけで

  other_struct s;
  s.loadFromJsonFile("hoge.json");
  s.loadFromJsonString("{\"objs\":[]}");

  s.writeToJsonFile("bar.json");
  std::string str = s.toJsonString();

  ofJson json = s;

といったファイルへの書き込み/読み込み, 文字列の書き出し/読み込み, オペレーターオーバーロードを裏で実装してくれます.

create, load

最初の例の

struct my_struct {
  ofVec3f point;
  int radius;
  ofJson toJson() const {
    ofJson json;
    json["point"] = ofxJsonUtils::convert(point);
    json["raidus"] = radius;
    return json;
  }
  void loadJson(const ofJson &json) {
    ofxJsonUtils::parse(json["point"], point);
    ofxJsonUtils::parse(json["radius"], radius);
  }
};

は, create / load を使うと次のようにも書けます.

struct my_struct {
  ofVec3f point;
  int radius;
  ofJson toJson() const {
    return ofxJsonUtils::create("point", point, "radius", radius);
  }
  void loadJson(const ofJson &json) {
    ofxJsonUtils::load(json, "point", point, "radius", radius);
  }
};

更に, kv マクロを使うと

struct my_struct {
  ofVec3f point;
  int radius;
  ofJson toJson() const {
    return ofxJsonUtils::create(kv(point), kv(radius));
  }
  void loadJson(const ofJson &json) {
    ofxJsonUtils ::load(json, kv(point), kv(radius));
  }
};

と書けます.

oFクラスの対応状況

現状は

  • ofVec2f: {"x": 0.0, "y": 0.0}
  • ofVec3f: {"x": 0.0, "y": 0.0, "z": 0.0}
  • ofVec4f: {"x": 0.0, "y": 0.0, "z": 0.0, "w": 0.0}
  • ofRectangle: {"x": 0.0, "y": 0.0, "width": 0.0, "height": 0.0}
  • ofMatrix4x4: {"value0": (ofVec4f), "value1": (ofVec4f), "value2": (ofVec4f), "value3": (ofVec4f)}
  • ofColor_<Type>: {"r": (Type), "g": (Type), "b": (Type), "a": (Type)}
  • std::vector<Type>, std::deque<Type>, std::array<Type> : [(Type) ...]
  • std::map<std::string, Type>: {key: (Type)}

といった感じで対応しています.

最後に

まだ書き始めたばかりなので欲しい機能があった場合はissue立ててもらえると有難いです.
もちろん, 機能追加やバグフィクスのPRもお待ちしております.

以上, 宣伝でした.

7
2
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
7
2