前:橋本商会 C++でmapやvectorをJSON出力するjson_builder.hを作った


ダブルクオートなどを含む文字列を値に保持するためのエスケープ処理にboost::regexを使ったので、libboost_regex-mt.aをコンパイル時に読み込まないとならなくなった → Makefileの例
まさかboost::regex_replaceで頭にバックスラッシュをつけるのに、バックスラッシュ4つで置換するとは思わなかった


こんな風に使う。true, false, nullを入れられるようになった
test.cpp

#include <iostream>
#include <string>
#include <map>
#include <boost/any.hpp>
#include "../json_builder.h"

int main(int argc, char* argv[]){
  std::map<string,boost::any> user;
  user["name"] = std::string("shokai");
  user["fullname"] = std::string("sho hashimoto");
  user["age"] = 25;
  user["test"] = 1.23;
  user["null"] = json_builder::null;
  user["true"] = true;
  user["false"] = false;

  string json = json_builder::toJson(user);
  cout << json << endl;
  return 0;
}


実行結果
{"age":"25","false":false,"fullname":"sho hashimoto","name":"shokai","null":null,"test":"1.23","true":true}



C++でnullを表現するために適当な構造体を定義してしまったけど、こういうので良いんだろうか?
json_builder.h
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <boost/any.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/regex.hpp>

using namespace std;
using namespace boost;

#define null json_null()

namespace json_builder{
  struct json_null{};

  string toJson(any value){
    if(value.type() == typeid(vector<any>)){
      string result_str;
      vector<any> vec = any_cast<vector<any> >(value);
      for(int i = 0; i < vec.size(); i++){
result_str += toJson(vec[i]);
if(i < vec.size()-1) result_str += ",";
      }
      result_str = str(format("[%s]") % result_str);
      return result_str;
    }
    else if(value.type() == typeid(map<string,any>)){
      string result_str;
      map<string,any> m = any_cast<map<string,any> >(value);
      string key;
      any value;
      int i = 0;
      BOOST_FOREACH(tie(key,value), m){
result_str += str(format("\"%s\":%s") % key % toJson(value));
if(++i < m.size()) result_str += ",";
      }
      result_str = str(format("{%s}") % result_str);
      return result_str;
    }
    else if(value.type() == typeid(json_null)){
      return string("null");
    }
    else if(value.type() == typeid(string)){
      return str(format("\"%s\"") % 
   regex_replace(any_cast<string>(value), regex("[\"\'\\\\/]"), "\\\\$0"));
    }
    else if(value.type() == typeid(bool)){
      if(any_cast<bool>(value)) return string("true");
      return string("false");
    }
    else if(value.type() == typeid(int)){
      return str(format("\"%d\"") % any_cast<int>(value));
    }
    else if(value.type() == typeid(double)){
      return str(format("\"%d\"") % any_cast<double>(value));
    }
  }

}