Shan.JSON 간단 매뉴얼 (Manual)

 Shan.JSON은 C++로 개발된 JSON 라이브러리입니다. Header only 형태로 배포되므로 프로젝트의 include path에 경로를 추가하여 사용합니다. 라이센스는 BSD 라이센스에 준하여 배포됩니다. Xcode 8.1, gcc 4.9.2, MSVC 2015에서 C++11으로 빌드 및 테스트되었습니다. C++11이전 버전은 지원하지 않으며 기타 다른 환경에서는 약간의 수정이 필요할 수 있습니다.

 일단 아래 주소에서 소스를 내려받습니다. 그 안에 shan 폴더가 있는데 그 폴더를 프로젝트의 원하는 위치로 옮기고 프로젝트의 헤더 파일 경로에 shan 폴더의 경로를 추가합니다.

 https://github.com/shanpark/Shan.Lib

헤더파일 include

 모든 라이브러리가 그렇듯 가장 먼저 Shan.JSON 라이브러리를 사용하고자 하는 소스에 헤더파일을 include 합니다.
#include <shan/json.h>

Constructing JSON objects from string(stream)

>> Constructing object
try {
  shan::json::object emptyObj; // empty object. {}

  shan::json::object j1("{\"key\":\"value\"}"); // constructed from 'const char*'
                                                // {"key":"value"}
  std::string json_str("{\"number\":100}");
  shan::json::object j2(json_str); // constructed from std::string. {"number":100}

  std::istringstream json_stream("{\"true_val\":true}");
  shan::json::object j3(json_stream); // constructed from std::istream. 
                                      // {"true_val":true}

  shan::json::object j4(j1); // copy constructor.
  shan::json::object j5(std::move(j2)); // move constructor. j2 will be empty.

  ...
} catch (const shan::json::bad_format_error& e) {
  ... 
}
>> Constructing array
try {
  shan::json::array emptyArr; // empty array. []

  shan::json::array a1("[\"str_val\", true, null]"); // constructed from 'const char*'.
                                                     // ["str_val",true,null]
  std::string json_str("[1, 3.14, true]");
  shan::json::array a2(json_str); // constructed from std::string. [1,3.14,true]

  std::istringstream json_stream("[false, 1.1e2]");
  shan::json::array a3(json_stream); // constructed from std::istream. [false,1.1-e2]

  shan::json::array a4(a1); // copy constructor
  shan::json::array a5(std::move(a2)); // move constructor. a2 will be empty.

  ...
} catch (const shan::json::bad_format_error& e) {
  ...
}

Printing JSON objects (to stream, string)

>> Printing object to stream & Converting object to string
shan::json::object j1("{\"key\":\"value\"}");
shan::json::object j2("{\"number\":100}");

std::cout << j1; // output to stdout. {"key":"value"}

std::ostringstream os;
os << j2; // output to std::istream. {"number":100}

std::string json_text1 = j2.str(); // json_text1 = {"number":100}
std::string json_text2 = j2.json_str(); // json_text2 = {"number":100}
                                        // object's str() & json_str() is equal.
>> Printing array to stream & Converting array to string
shan::json::array a1("[\"str_val\", true, null]");
shan::json::array a2("[1, 3.14, true]");

std::cout << a1; // output to stdout. ["str_val",true,null]

std::ostringstream os;
os << a2; // output to std::istream. [1,3.14,true]

std::string json_text1 = a2.str(); // json_text1 = [1,3.14,true]
std::string json_text2 = a2.json_str(); // json_text2 = [1,3.14,true]
                                        // array's str() & json_str() is equal.

Accessing JSON objects

>> Accessing object values
shan::json::object json(u8R"(
{
  "int":12345, "real":123.45, "true":true, "false":false, "null":null,
  "string":"12345",
  "arr":[1, 2.0, true, false, null, [1, 2.0, true, false], {"int":123}],
  "obj":{"int":123, "real":12.3}
}
                            )");

try {
  json["int"]->int_val(); // 12345, json["int"] is shared_ptr<value>.
                     // object pointed by json["int"] => 'number' class object.
                     // for convenience, 'shared_ptr<number>'.
  json["real"]->real_val(); // 123.45, json["real"] => shared_ptr<number>
  json["real"]->int_val();  // 123, int & real values are implicitly converted.

  json["true"]->bool_val();  //  true, json["true"] => shared_ptr<true_value>
  json["false"]->bool_val(); // false, json["false"] => shared_ptr<false_value>

  json["null"]->is_null(); // true. json["null"] => shared_ptr<null_value>

  json["string"]->str()      // 12345, not quoted.
  json["string"]->json_str() // "12345", quoted.
                             // json["string"] => shared_ptr<string>
                      // str() and json_str() differ only for the string class.

  json["arr"]->size(); // 7, array is compatible vector<value>
  json["arr"]->at(0)->int_val(); // 1, json["arr"] => shared_ptr<array>
                                 // json["arr"]->at(0) => shared_ptr<number>

  json["obj"]->size(); // 2, object is compatible map<string, value>
  json["obj"]->at("int")->int_val(); // 123, json["obj"] => shared_ptr<object>
                                 // json["obj"]->at("int") => shared_ptr<number>
  // Another way to access objects and arrays will be shown in the following
  // array example.
} catch (const shan::json::not_allowed_error& e) {
  // unreasonable call throws an exception!
  // json["int"]->bool_val(); // error !
  // json["null"]->int_val(); // error !
  // json["true"]->at(0); // error !
  // ...
  // is_xxx(), str(), json_str() can be called from all class.
}
>> Accessing array elements
shan::json::array arr(u8R"(
[ 
  12345, 123.45, true, false, null,
  [1, 2.0], {"int":123, "real":12.3}
]
                          )");

try {
  arr[0]->int_val();  // 12345
  arr[2]->bool_val(); // true
  arr[4]->is_null(); // true

  auto& arr2 = *arr[5]; // arr2's type => value&(In fact, array&)
  arr2[0]->int_val(); // 1

  auto& obj = *arr[6]; // obj's type => value&(In fact, object&)
  obj["real"]->real_val(); // 12.3, 
} catch (const shan::json::not_allowed_error& e) {
  ... // unreasonable call throws an exception!
}

Modifying JSON objects

>> Modifying object
shan::json::object json; // empty object

json.add("int", 1); // "int":1
json.add("real", 3.14); // "real":3.14
json.add("true", true); // "true":true
json.add("null", null); // "null":null
json.add("string", "value"); // "string":"value"

shan::json::array arr("[1, 2, 3]");
json.add("array", arr); // "array":[1, 2, 3]
json.add("array_move", std::move(arr)); // "array_move":[1, 2, 3]
                                        // arr will be empty. (move semantics)

shan::json::object obj("{\"key\":10}");
json.add("obj", obj); // "obj":{"key":10}
json.add("obj_move", std::move(obj)); // "obj_move":{"key":10}
                                      // obj will be empty. (move semantics)

// object inherits std::map<string, value_ptr>. 
// You can use methods of std::map.
json.erase("real"); // erase pair "real":3.14
json.clear(); // erase all elements.
>> Modifying array
shan::json::array arr; // empty array

arr.add(1); // add 1 at the end.
arr.add(3.14); // add 3.14 at the end.
arr.add(true); // add true at the end.
arr.add(null); // add null at the end.
arr.add("value"); // add "value" at the end.

shan::json::array arr2("[1, 2, 3]");
arr.add(arr2); // add [1, 2, 3] at the end.
arr.add(std::move(arr2)); // arr2 will be empty. (move semantics)

shan::json::object obj("{\"key\":10}");
arr.add(obj); // add {"key":10} at the end.
arr.add(std::move(obj)); // obj will be empty. (move semantics)

// array inherits std::vector<value_ptr>. 
// You can use methods of std::vector.
arr.erase(arr.begin()); // erase 1(first value)
arr.clear(); // erase all elements.

MesssagePack Compatibility

shan::json::object ori(......); // construct an object

// pack
auto bytes(ori.pack()); // ori.pack() generate MessagePack data.
                        // bytes = std::vector

std::vector bytes2; // out buffer.
ori.pack(bytes2); // bytes2 will contain MessagePack data.

// unpack
shan::json::object copy; // construct an empty object.
copy.unpack(bytes); // restore object from bytes vector(MessagePack data).
                    // copy == ori

shan::json::object copy2; // construct an empty object.
copy2.unpack(bytes2.data()); // restore object from 'const uint8_t*' 
                             //(MessagePack data array).
                             // copy2 == ori

// an array is the same as an object.
// pack
shan::json::array arr(......); // construct an array

auto bytes3(arr.pack()); // arr.pack() generate MessagePack data.
                         // bytes3 = std::vector<uint8_t>

// unpack
shan::json::array cpa; // construct an empty array.
cpa.unpack(bytes3); // restore array from bytes vector(MessagePack data).
                    // cpa == arr

Etc.

// type declaration
using value_ptr = std::shared_ptr<value>; // object, array class contain this.
using const_value_ptr = std::shared_ptr<const value>;

// STL compatible
using object_base = std::map<string, value_ptr>; // super class of shan::json::object
using array_base = std::vector<value_ptr>; // super class of shan::json::array
using string_base = std::string; // super class of shan::json::string

class object : public value, public object_base {...}
class array : public value, public array_base {...}
class string : public value, public string_base {...}

// In most cases, you will already know the types of values by your protocol.
// If not, you can use the functions below.
shan::json::array a;
...

if (a[0]->is_null()) // null
    ... // just null check.
if (a[0]->is_number()) // int or real
    ... // int_val(), real_val()
if (a[0]->is_bool()) // true or false
    ... // bool_val()
if (a[0]->is_string()) // string
    ... // std::string compatible
if (a[0]->is_array()) // array
    ... // size(), at(), operator[], std::vector compatible
if (a[0]->is_object()) // object
    ... // size(), at(), operator[], std::map compatible

// NOTE!
// shan::object and shan::json::object are different classes.
// shan::object is the root class of all Shan.Lib classes.
// shan::json::object is a kind of JSON object class(std::map compatible).
// value class is a base class of all JSON classes.

댓글 1개: