Skip to content
Convert between json string and c++ object. json字符串和c++结构体之间互相转换
Branch: master
Clone or download
huangxiyuan
huangxiyuan fix readme error
Latest commit bb106b9 Apr 15, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
test Optimize customize types Mar 31, 2019
thirdparty fix warning of noexcept and 32bit compiler Mar 18, 2019
README.md
README.zh-cn.md
bson_builder.h
bson_reader.h
bson_writer.h
config.h
config_reader.h
config_writer.h
go_writer.h support char array Dec 21, 2018
json_reader.h
json_writer.h Refactoring conditional loading Mar 26, 2019
rapidjson_custom.h
traits.h
util.h
x2struct.hpp modify readme and fix local class bug Mar 31, 2019
xml_reader.h
xml_writer.h
xreader.h
xtypes.h

README.md

x2struct

Read this in other languages: 简体中文.

  • Used to convert between C++ objects and json/xml/json/libconfig
  • json/xml is header file only, no need to compile librarys
  • json is enabled by default, others need to modify config.h
  • The following example uses json as an example. Others can refer to api of x2struct::X in x2struct.hpp

Basic usage

#include <iostream>
#include "x2struct/x2struct.hpp" // include this header file

using namespace std;

struct User {
    int64_t id;
    string  name;
    string  mail;
    User(int64_t i=0, const string& n="", const string& m=""):id(i),name(n),mail(m){}
    XTOSTRUCT(O(id, name, mail)); // add XTOSTRUCT at the end of struct/class
};

struct Group {
    string  name;
    int64_t master;
    vector<User> members;
    XTOSTRUCT(O(name, master, members)); //  add XTOSTRUCT at the end of struct/class
};

int main(int argc, char *argv[]) {
    Group g;
    g.name = "C++";
    g.master = 2019;
    g.members.resize(2);
    g.members[0] = User(1, "Jack", "jack@x2struct.com");
    g.members[1] = User(2, "Pony", "pony@x2struct.com");

    string json = x2struct::X::tojson(g);  // C++ object to json
    cout<<json<<endl;

    Group n;
    x2struct::X::loadjson(json, n, false); // json to C++ object
    cout<<n.name<<endl;

    vector<int> vi;
    x2struct::X::loadjson("[1,2,3]", vi, false); // load vector directory
    cout<<vi.size()<<','<<vi[1]<<endl;

    map<int, int> m;
    x2struct::X::loadjson("{\"1\":10, \"2\":20}", m, false); // load map directory
    cout<<m.size()<<','<<m[2]<<endl;

    return 0;
}
  • include "x2struct.hpp"
  • add XTOSTRUCT at the end of struct, put all the variables inside "O"
  • use x2struct::X::tojson to convert C++ object to json
  • use x2struct::X::loadjson to load json to C++ object

Mandatory

  • for json to C++ object
  • use M to include those mandatory variables
  • if mandatory field miss in json, an exception will throw
#include <iostream>
#include "x2struct/x2struct.hpp"

using namespace std;

struct Test {
    int64_t id;
    string  name;
    XTOSTRUCT(M(id), O(name)); // "id" is mandatory and "name" is optional
};

int main(int argc, char *argv[]) {
    Test t;
    string json="{\"name\":\"Pony\"}";

    x2struct::X::loadjson(json, t, false); // will throw exception(id is mandatory and no "id" in json)
    return 0;
}

Alias

  • used for scenes where the variable name and json key name are inconsistent
  • use A to include alias variable. "A" take two parameters, 1st is variable, 2nd is tag-field
  • tag format is "[type:]alias[,extension]", Tag-field can contain multiple tags, separated by spaces
  • type is one of "json"/"xml"/"bson"/"config", no type field in tag means this tag is applied to all type
    • for example, "tid" means use tid as alias for all type
    • "tid json:xid" means json use "xid" as alias and other types use "tid"
  • extension only support "m" now, means mandatory(A like O, optional)
  • if no alias in json, loadjson will also try variable name
  • tojson use alias
#include <iostream>
#include "x2struct/x2struct.hpp"

using namespace std;

struct Test {
    int64_t uid;
    string  name;
    XTOSTRUCT(A(uid, "id"), O(name)); // "uid" use alias "id"
};

int main(int argc, char *argv[]) {
    Test t;
    string json="{\"id\":123, \"name\":\"Pony\"}";

    x2struct::X::loadjson(json, t, false); 
    cout<<t.uid<<endl;
    return 0;
}

Inherit

  • use I to include parents classs
#include <iostream>
#include "x2struct/x2struct.hpp"

using namespace std;

struct P1 {
    string mail;
    XTOSTRUCT(O(mail));
};

struct P2 {
    int64_t version;
    XTOSTRUCT(O(version));
};

struct Test:public P1, public P2 {
    int64_t uid;
    string  name;
    XTOSTRUCT(I(P1, P2), O(uid, name)); 
};

int main(int argc, char *argv[]) {
    Test t;
    string json="{\"mail\":\"pony@x2struct.com\", \"version\":2019, \"id\":123, \"name\":\"Pony\"}";

    x2struct::X::loadjson(json, t, false);
    cout<<t.mail<<endl;
    cout<<t.version<<endl;
    return 0;
}

Bit field

  • use B to include those bit field variables
#include <iostream>
#include "x2struct/x2struct.hpp"

using namespace std;

struct Test {
    int16_t ver:8;
    int16_t len:8;
    string  name;
    XTOSTRUCT(B(ver, len), O(name)); 
};

int main(int argc, char *argv[]) {
    Test t;
    string json="{\"ver\":4, \"len\":20, \"name\":\"IPv4\"}";

    x2struct::X::loadjson(json, t, false);
    cout<<t.ver<<endl;
    cout<<t.len<<endl;
    return 0;
}

Load conditional

  • load at most one object from an array of objects
  • use C to include those conditional variables at the beginning of XTOSTRUCT
  • conditional variables still need included in one of O,A or M
#include <iostream>
#include "x2struct/x2struct.hpp"

using namespace std;

struct Task {
    int id;
    string name;
    XTOSTRUCT(O(id, name));
};

struct Test {
    int  tid;
    Task task;
    XTOSTRUCT(C(task), O(tid, task)); // task included in C and O, C must at beginning of XTOSTRUCT
    /*
     XTOSTRUCT_CONDITION take two parameters, 1st is class name, 2nd is variable name
     XTOSTRUCT_CONDITION defined a function take one parameter named "obj", pointer to xdoc of variable
     "task" in json is array, load conditional only load the one that this functin return true
    */
    XTOSTRUCT_CONDITION(Test, task) {
        int id;
        // only load the one that Task.id is equal to Test.tid
        return obj.convert("id", id)&&id==this->tid;
    }
};



int main(int argc, char *argv[]) {
    string s = "{\"tid\":2019,\"task\":[{\"id\":2018,\"name\":\"hello\"},{\"id\":2019,\"name\":\"world\"}]}";
    Test t;
    x2struct::X::loadjson(s, t, false);
    cout<<t.task.name<<endl;
}

char array

modify config.h to enable XTOSTRUCT_SUPPORT_CHAR_ARRAY

check exist

  • to check if field exist after load json to C++ object
  • use xhas to check if field exist
#include <iostream>
#include "x2struct/x2struct.hpp"

using namespace std;

struct Test {
    int64_t id;
    string  name;
    XTOSTRUCT(O(id, name));
};

int main(int argc, char *argv[]) {
    Test t;
    string json="{\"name\":\"Pony\"}";

    x2struct::X::loadjson(json, t, false, true); // 4th parameter apply true
    cout<<t.xhas("id")<<endl;       // use xhas to check exist
    cout<<t.xhas("name")<<endl;
    return 0;
}

local class

  • XTOSTRUCT will add some template function, and local class could not define template function
  • use XTOSTRUCT_NT(types) instead of XTOSTRUCT, types support Json/Xml/Bson/Config
  • need C++11 support
  • not support load conditional now
// nt.cpp
// g++ -o t nt.cpp -std=c++11
#include <iostream>
#include "x2struct/x2struct.hpp"

using namespace std;

int main(int argc, char *argv[]) {
    struct Test {
        int64_t id;
        string  name;
        XTOSTRUCT_NT(Json)(O(id, name));
    };

    Test t;
    string json="{\"id\":123, \"name\":\"Pony\"}";

    x2struct::X::loadjson(json, t, false);
    cout<<t.name<<endl;
    return 0;
}

customize type

  • customize type is string
  • need implement:
    • std::string format() const; use to format data to string
    • void parse(const std::string&); use to load string to data
  • typedef XType to define customize type
  • following is an IPv4 example
#include <iostream>
#include "x2struct/x2struct.hpp"

using namespace std;

// just example, no error handle
struct _XIPv4 {
    uint32_t ip;
    std::string format() const {
        char buf[64];
        int  len = sprintf(buf, "%u.%u.%u.%u", ip>>24, 0xff&(ip>>16), 0xff&(ip>>8), 0xff&ip);
        return string(buf, len);
    }
    void parse(const std::string& d) {
        uint32_t u[4];
        sscanf(d.c_str(), "%u.%u.%u.%u", &u[0], &u[1], &u[2], &u[3]);
        ip = (u[0]<<24)+(u[1]<<16)+(u[2]<<8)+u[3];
    }
};

typedef x2struct::XType<_XIPv4> XIPv4;

struct Test {
    XIPv4 ip;
    XIPv4 mask;
    XTOSTRUCT(O(ip, mask));
};

int main(int argc, char *argv[]) {
    Test t;
    string json="{\"ip\":\"192.168.1.2\", \"mask\":\"255.255.255.0\"}";

    x2struct::X::loadjson(json, t, false);
    cout<<t.ip.ip<<','<<t.mask.ip<<endl;
    cout<<x2struct::X::tojson(t)<<endl;
    return 0;
}

Format indent

  • last two parameters of tojson control format indent

xml bson libconfig

  • need to modify config.h to enable
  • not support load vector map directory
  • xml/libconfig not permit use digit as key, so if want to use map<int, xxx>, key need add 'x', e.g. x100
  • mongoxclient(https://github.com/xyz347/mongoxclient) is a wrapper of mongo-cxx-driver use bson

Generate Golang struct

  • use to generate Golang struct define by C++ struct
  • need to define macro XTOSTRUCT_GOCODE
// go.cpp
// g++ -o t go.cpp -DXTOSTRUCT_GOCODE
#include <iostream>
#include "x2struct/x2struct.hpp"

using namespace std;

struct Test {
    int64_t id;
    vector<string>  names;
    XTOSTRUCT(O(id, names));
};

int main(int argc, char *argv[]) {
    Test t;

    cout<<x2struct::X::togocode(t, true, true, true)<<endl; // last 3 parameter to generate (json/bson/xml) tags
    return 0;
}

output is:

type Test struct {
        Id      int64       `json:"id" bson:"id" xml:"id"`
        Names   []string    `json:"names" bson:"names" xml:"names"`
}

IMPORTANT

  • Encode/decode json is use rapidjson
  • Decode xml is use rapidxml
  • Decode bson is use libbson
  • Decode libconfig is use libconfig
  • Encode of xml/bson is written by myself. Without reference to the RFC, there may be cases where the standard is not met.
  • The library of bson/libconfig is precompiled. The environment is: Ubuntu12.04 g++4.9.2. Other environments may need to download the code and recompile if you need to use these two libraries.
You can’t perform that action at this time.