ctl::jsonはC++用のheader-onlyなJSONテンプレートライブラリです。
ctl::jsonはC++のjsonライブラリです。特徴は次の通りです。
動作確認済みコンパイラのうちもっとも古いものはVC++2005です。
ctljson.hppをincludeするだけです。
ctl::json型インスタンスを作り、そのメンバ函数parse()にJSONデータ文字列(std::stringまたはnull終端文字列)を渡します。
// Example 01: ctl::json root; const std::string jsondata = R"({ "a": 1, "b": { "b1": "#", "b2": "%" } })"; root.parse(jsondata); // JSONの読み込み。 printf(R"(["a"] = %d, ["b"]["b1"] = "%s")" "\n", root["a"].num<int>(), root["b"]["b1"].str().c_str()); // 出力結果: // ["a"] = 1, ["b"]["b1"] = "#"
読み込みは、コンストラクタにJSONデータを渡すことによっても可能です。
// Example 02: ctl::json root(R"({ "c": 2, "d": { "d1": "##", "d2": "%%" } })"); printf(R"(["c"] = %d, ["d"]["d2"] = "%s")" "\n", root["c"].num<int>(), root["d"]["d2"].str().c_str()); // 出力結果: // ["c"] = 2, ["d"]["d2"] = "%%"
ctl::json型インスタンスのstringify()メンバ函数またはto_string()メンバ函数を呼び出すと、JSONデータ化されたstd::string型文字列が返ってきます。
この2つのメンバ函数は名前が違うだけで挙動に違いはありません。前者はJavaScript由来の名前で、後者はC++風の名前です。
// Example 03: ctl::json root, childnode; childnode(0) = "zero"; childnode(1) = "one"; root("obj") = childnode; root("str") = "ABC"; const std::string jsondata = root.stringify(); // JSONの書き出し。 // const auto jsondata = root.stringify<std::string>(); // テンプレート引数により、戻り値の型を明示的に指定することも可能。 printf("%s\n", jsondata.c_str()); // 出力結果: // {"obj":["zero","one"],"str":"ABC"}
当ライブラリには ctl::json, ctl::u8json, ctl::wjson, ctl::u16json という4つの型が存在します。これらは文字列の保持の仕方が異なるだけで使い方は同じです(前2つは文字列をUTF-8型で保持し、後の2つはUTF-16型で保持)。以下では ctl::json を使って解説を行います。
ctl::json型インスタンスは、RFC 8259に定められた「数値、文字列、配列、オブジェクト、または true, false, null という3つのリテラル名」を値として保持することが出来ます。
配列またはオブジェクトの各要素は、それ自体もctl::json型のインスタンスです。従いまして、例えば「配列の1番要素の2番目のデータ」には js[1][2] でアクセスすることが出来ます。
あるインスタンスが今現在どの型を保持しているかは、type()メンバ函数によって調べられます。この函数の戻り値はctl::json::value_typeという名前のenum型で、値としてnumber(数値), string(文字列), array(配列), object(オブジェクト), boolean(trueかfalseのみ保持できる), null, unassigned, fallbackが定義されています。
今保持しているタイプと異なるタイプのデータを書き込んでもエラーとはなりません。タイプ情報も併せて書き換えられます。
配列とオブジェクトについては、添え字の要素にアクセスする方法が2種類あります。
operator()()によるアクセス。読み書きとも常に実在する要素への参照を返します。配列の場合、添え字nがその配列のサイズ以上である時は、まず配列をn+1まで拡張した上で[n]への参照を返します。オブジェクトの場合も、nというキー名の要素がない時はまずそのような名前の要素を作り、その上でそこへの参照を返します。operator[]()によるアクセス。該当する要素が存在している場合はそこへの参照を返しますが、存在しない場合は「フォールバックノード」という特殊な要素への参照を返し、要素を新規作成しません。ツリー構造を変えないことが保証されているアクセス方法です。
「フォールバックノード」とは、operator[]()を使ってJSONツリー上のデータにアクセスする際、該当する要素が存在しなかった場合に代わりにreturnされてくる特殊な要素です。
// Example 04: ctl::json root(R"({ "a": 1, "b": 2 })"); printf(R"(root["c"] = %d, root("d") = %d)" "\n", root["c"].num<int>(), root("d").num<int>()); // ツリー上に存在しない ["c"] や ("d") にアクセスしている。 const std::string jsondata = root.stringify(); // JSONの書き出し。 printf("%s\n", jsondata.c_str()); // 出力結果: // root["c"] = 0, root("d") = 0 // {"a":1,"b":2,"d":null}
上のExample 04では、operator[]()によってアクセスされた root["c"] のほうは要素が新規作成されていないのに対し、operator()()によってアクセスされた root("d") のほうは要素が作られてしまっています(値が null になっているのは何も代入されていないためです)。
ある要素が実在する要素なのかフォールバックノードなのかは、exists()メンバ函数(実在するならtrueを返す)またはis_fallback()メンバ函数(フォールバックノードならtrueを返す)によって判別できます。
// Example 05: ctl::json root(R"({ "a": 1 })"); printf(R"(["a"] = %d/%d)" "\n", root["a"].exists(), // root.exists("a") とも書ける。 root["a"].is_fallback()); printf(R"(["b"] = %d/%d)" "\n", root["b"].exists(), root["b"].is_fallback()); // 出力結果: // ["a"] = 1/0 // ["b"] = 0/1
フォールバックノードの子孫はすべてフォールバックノードです。operator[]()を使えば、ツリー構造が変わってしまう心配をすることなく、安心して深い階層にアクセスすることが出来ます。
// Example 06: ctl::json root(R"({ "a": 1 })"); printf(R"(["a"]["b"]["c"] = %d/%d)" "\n", root["a"]["b"]["c"].exists(), root["a"]["b"]["c"].is_fallback()); // 出力結果: // ["a"]["b"]["c"] = 0/1
フォールバックノードに値を代入することは出来ません。左辺値にしてもエラーにはならず、単に無視されます。
また、フォールバックノードの下の階層に()で要素を作ろうとしても無視されます。
// Example 07: ctl::json root(R"({ "a": 1 })"); root["a"]["b"]("c") = 2; // 存在しない ["b"] の下に ("c") を作ろうとしている。 printf(R"(["a"]["b"]("c") = %d/%d %d)" "\n", root["a"]["b"]("c").exists(), root["a"]["b"]("c").num<int>(), root["a"].num<int>()); // 出力結果: // ["a"]["b"]("c") = 0/0 1 // ["a"] の値は1という数値のまま。オブジェクト型に変わっていない。
ctl::json, ctl::wjson, ctl::u16json, ctl::u8json classのメンバについての情報です。
次の型がtypedefされています。
| char_type | string_type | sview_type | 備考 | |
|---|---|---|---|---|
| ctl::json | charのtypedef. |
std::stringのtypedef. |
std::string_view相当。 |
|
| ctl::u8json | char8_tのtypedef. |
std::u8stringのtypedef. |
std::u8string_view相当。 |
C++20以降のみ。 |
| ctl::wjson | wchar_tのtypedef. |
std::wstringのtypedef. |
std::wstring_view相当。 |
WCHAR_MAXが0xffff以上、0x110000未満の時のみ定義。 |
| ctl::u16json | char16_tのtypedef. |
std::u16stringのtypedef. |
std::u16string_view相当。 |
C++11以降のみ。 |
sview_typeはC++17以降のstd::string_view相当のクラスです。std::string型の文字列コンテナとnull終端文字列へのポインタとの両方を扱うことができます。std::string_viewそのものではありませんので、C++14以前のコンパイラでも使用できます。
ctl::jsonとctl::u8jsonとのsview_typeは、UTF-8文字列の受け渡しに使います。
ctl::wjsonとctl::u16jsonとのsview_typeは、UTF-16文字列の受け渡しに使います。
表の備考欄にもあります通り、ctl::wjsonはWCHAR_MAXが0xFFFF以上、0x110000未満の時のみ定義されます。事実上Windows用です。
インスタンスが保持しているデータの種別を表すものとして、次のものが定義されています。
enum value_type
{
// Version 2.109以降。
array, object, number, string, boolean, null, unassigned, fallback
// Version 2.108まで。
null, boolean, number, string, array, object, unassigned, fallback
};
メンバ函数type()の返値がこの型です。
numberは数値型、stringは文字列型、arrayは配列型、objectは文字を添え字とする配列型をそれぞれ意味します。
booleanはtrueかfalseのみを値として保持できる型のことです。
最後の2つは内部で使用する型です。引数無しのコンストラクタで作られたインスタンスはunassigned型になっています。
publicなものとしては以下の6種類があります。
| json(); | (1) |
| json(const json &right); | (2) |
|
template <typename StringType> explicit json(const StringType &s); |
(3) |
|
template <typename StringType> json(const StringType &s, json_error &e); |
(4) (2.112以降) |
|
template <typename Iterator> json(Iterator begin, Iterator end); |
(5) |
|
template <typename Iterator> json(Iterator begin, Iterator end, json_error &e); |
(6) (2.112以降) |
この他、フォールバックノードを作るためのものがprivateなコンストラクタとして存在しています。
(3) parse(s)を呼びます。
(4) parse(s, e)を呼びます。
(5) parse(begin, end)を呼びます。
(6) parse(begin, end, e)を呼びます。
(3)と(5)に限り、パーズ中にエラーが発生した場合はclear()が呼ばれます(エラー発生を通知する方法がないため)。
Version 2.106以降、(3)のコンストラクタの引数はstring_typeではなくなりましたので、任意の文字列型を渡すことも出来ます。
|
template <typename StringType> bool parse(const StringType &s) |
(1) |
|
template <typename StringType> bool parse(const StringType &s, json_error &e) |
(2) (2.112以降) |
|
template <typename CharType> bool parse(const CharType *p) |
(3) |
|
template <typename CharType> bool parse(const CharType *p, json_error &e) |
(4) (2.112以降) |
|
template <typename Iterator> bool parse(Iterator begin, Iterator end) |
(5) |
|
template <typename Iterator> bool parse(Iterator begin, Iterator end, json_error &e) |
(6) (2.112以降) |
(1)(2)は任意の文字列コンテナStringType型(std::basic_stringそのものかAPI互換のもの)の文字列sを、(3)(4)は任意の文字型CharTypeからなるnull終端文字列へのポインタpを、(5)(6)は[begin, end)を、それぞれUTF-8で符号化されたJSONデータと見なしてパーズします。パーズが完走したらtrueを返します。
途中でエラーが発生した場合はfalseを返します。それに先だって(2)(4)(6)はエラーの理由をeにセットします。
パーズの際、文字列中のエスケープされた文字(\" \t \nなど)についてはすべてアンエスケープされます。
この点を除き、ctl::jsonとctl::u8jsonとは入力文字列を解釈しません。たとえUTF-8として不正な並びがあってもそのまま取り込みます。
一方ctl::wjsonとctl::u16jsonとは、UTF-16に変換できない箇所があればそこでパーズが止まります。
(5)と(6)のIteratorはforward iterator以上であれば動きますが、エラー発生時にはstd::distance()を使って位置を算出しますので、random access iterator以上の使用をお勧めします。
Version 2.106以降、(1)(3)は引数がそれぞれstring_type, const char_type *ではなくなりましたので、任意の文字列型を渡すことも出来ます。
Version 2.111までは、パーズ失敗時にはclear相当の処理をしていましたが、2.112以降は正常に読み取れた部分はそのまま保持します。
BreakingChangeVersion 2.111まで(5)のイテレータペアを引数として取るものは、パーズが終わった時点もしくは止まった時点のイテレータを戻り値として返してきました。Version 2.112以降は、エラーの情報をjson_error &eで受け取ることができるようになりましたので、(1)や(3)同様に単にパーズの成否をbool値で返すようになっています。
| string_type stringify() const | (1) |
| string_type to_string() const | (2) |
|
template <typename StringType> StringType stringify() const |
(3) (2.106以降) |
|
template <typename StringType> StringType to_string() const |
(4) (2.106以降) |
|
template <typename StringType> void stringify(StringType &out) const |
(5) (2.112以降) |
|
template <typename StringType> void to_string(StringType &out) const |
(6) (2.112以降) |
保持している値をUTF-8形式のJSONデータ文字列に変換し、(1)(2)(3)(4)はその文字列を返します。(5)(6)は変換したものをoutに出力します。"や\など、そのまま出力できない文字についてはエスケープ処理が行われます。
stringify()とto_string()とは名前が違うだけで挙動に違いはありません。前者はJavaScript由来の名前で、後者はC++風の名前です。
フォールバックノードや種別がjson::unassignedのインスタンスは null を出力します。
Version 2.106以降、戻り値の文字列型はテンプレート引数によって明示的に指定することができます。省略時はstring_type型で返されます。
インスタンスが保持している値をclearし、種別をunassignedに戻します。
保持している値の種別を返します。返り値はvalue_type型の整数です。
保持している値の種類が数値ならtrueを返します。
保持している値の種類が文字列ならtrueを返します。
保持している値の種類がboolean型ならtrueを返します。
保持している値の種類がboolean型かつ値がtrueならtrueを返します。
保持している値の種類がboolean型かつ値がfalseならtrueを返します。
保持している値の種類がnullならtrueを返します。
保持している値の種類が配列ならtrueを返します。
保持している値の種類がオブジェクトならtrueを返します。
フォールバックノードならtrue、そうでないならfalseを返します。
有効な値を保持していればtrue、そうでないならfalseを返します。falseを返すのは「インスタンスが作られてからまだ何も代入されていない時」「clear()された直後」「直前のparse()が失敗した時」または「自身がフォールバックノードである場合」です。
| bool exists() const | (1) |
| bool exists(const std::size_t no) const | (2) |
| bool exists(const sview_type key) const | (3) |
(1) インスタンスがフォールバックノードではなく実在する要素ならtrue、そうでないならfalseを返します。
(2) インスタンスが配列を保持している時、no < size()かどうかを返します。配列を保持するインスタンスではないならfalseを返します。
(3) インスタンスがオブジェクトを保持している時、keyという添え字の要素が存在するかどうかを返します。保持するインスタンスがオブジェクト型ではないならfalseを返します。
| json &operator=(const json &right) | (1) |
| json &operator=(double right) | (2) |
| json &operator=(bool right) | (3) |
| json &operator=(const sview_type right) | (4) |
| json &operator=(const char_type *right) | (5) |
| json &operator=(const psnum &right) | (6) (2.115以降) |
| json &operator=(value_type right) | (7) (2.115以降) |
右辺値rightを自身(左辺値)にコピーします。現在のインスタンス種別と異なる場合は種別の変更も同時に行います。
(2) doubleのみならず引数が数値型の時にはこれが呼ばれます。set_num(right, -6)を呼び出します。
(3) 引数がbool値、trueまたはfalseの時に呼ばれ、set_bool(right)を呼び出します。
(4) 引数がstd::stringやstd::string_viewのような文字列コンテナの時に呼ばれ、set_str(right)を呼び出します。
(5) 引数が文字列へのポインタの時に呼ばれ、set_str(right)を呼び出します。
(6) 引数がpsnum型の時に呼ばれ、set_num(right.value, right.precision)を呼び出します。
(7) 引数rightの値によって自身(左辺値)を初期化します。ctl::json::nullならset_null()を呼び出します。引数rightがctl::json::arrayならempty_array()を、ctl::json::objectならempty_object()をそれぞれ呼び出します。
(2)や(6)の数値からの代入を行う際は、その数値と一緒に数値を文字列化したものも内部に保存されます。これはprintf系函数を("%.6f", right)という引数によって呼び出したのと同等の文字列化を行った上で、さらに元の数値が小数なら小数点以下にある末尾の0を文字列から削り、その結果小数点以下の数値がすべてなくなったら小数点そのものも取り除くという処理を行ったものに相当します。
たとえばjs1 = 1.23456789, js2 = 0.0 とすると、それぞれ"1.234568", "0"という文字列に変換されてインスタンス内部に保存されます。
この「文字列化された数値」は、stringify()やto_stringによってJSONテキストを書き出す時に使用されます。
小数点以下の丸め精度を変えたい場合や、末尾の0を取り除いてほしくない場合はメンバ函数set_num()か(6)を使います。
ECMAScript (JavaScript) は数値をIEEE 754の64-bit formatで保持します。これに倣い当ライブラリも数値はdouble型で保管します。
IEEE 754の64-bit formatは仮数部が53 bitですので、それを上回るビット数の整数を読み書きしようとすると誤差が発生します。これはECMAScript由来の仕様です。また、お使いのコンパイラのdouble型がIEEE 754準拠ではない場合にも誤差が発生する可能性があります。
精度の厳密さが求められる状況では、数値を文字列化して読み書きすることをお勧めします(js = 12.34 ではなく js = "12.34" のようにする)。
BreakingChange2.102までは文字列からの代入の際、文字列の中にエスケープされた文字(\" \t \nなど)があれば、それらはすべてアンエスケープされました。
| double num() const | (1) |
|
template <typename NumType> NumType num() const |
(2) (2.108以降) |
type() == json::numberの時は保持している数値を返します。
type() == json::booleanの時は、保持している値がtrueなら1.0を、falseなら0.0をそれぞれ返します。
type()がこれら以外の時は0.0を返します。
Version 2.108以降、戻り値の型はテンプレート引数で指定できます。省略時はdouble型で返されます。たとえばjs.num()と書くと戻り値はdouble型ですが、js.num<int>()のように書くとint型にキャストされた値が返ってきます。
| string_type numstr() const | (1) |
|
template <typename StringType> void numstr(StringType &out) const |
(2) (2.112以降) |
(1) はtype() == json::numberなら保持している数値を文字列化して返します。
type() == json::booleanの時は、保持している値がtrueなら"true"というリテラル文字列を、falseなら"false"というリテラル文字列をそれぞれ返します。
type() == json::nullなら"null"というリテラル文字列を返します。
type()がこれら以外の時は空の文字列を返します。
(2) はインスタンスが数値、boolean値、nullのどれかを保持している時は(1)と同じ変換をして、それを任意の文字列コンテナ型StringTypeのoutに出力します。他の種類のデータを保持している時はoutをclearして返ります。
すべての種類のデータを文字列化してほしい時は、前記のstringify() / to_string()を使います。
| string_type str() const | (1) |
|
template <typename StringType> void str(StringType &out) const |
(2) (2.112以降) |
(1) type() == json::stringの時は保持している文字列を返します。type()がそれ以外の時は空の文字列を返します。
(2) type() == json::stringの時は保持している文字列を任意の文字列コンテナ型StringTypeのoutに出力します。type()がそれ以外の時はoutをclearして返ります。
precisionが正数の時は、printf系函数の("%.*f", precision, d)に相当する文字列化を行い、その文字列を値dとともにインスタンス内に保持します。
precisionが負数の時は、まずprecisionを絶対値化した上で先の処理を行います。そして値dが小数なら小数点以下にある末尾の0を削り、小数点以下の数値がすべてなくなったら小数点そのものも取り除くという処理を行います。
set_num(0.123, 6) → "0.123000"set_num(0.123, -6) → "0.123"set_num(0.0, 6) → "0.000000"set_num(0.0, -6) → "0"
この「文字列化された数値」は、stringify()やto_stringによってJSONテキストを書き出す時に使用されます。
ちなみに前記のoperator=(double d)は、set_num(d, -6)を呼び出しています。
「数値型インスタンスは数値とそれを文字列化したものとを同時に保存している」という仕組みを利用して、JSONとは無関係に数値と文字列との相互変換を行うこともできます。
// 文字列から数値へ。 double dbl = ctl::json("1234.56789").num(); // dbl = 1234.567890; // 数値から文字列へ。 std::string str = ctl::json().set_num(1.234, 4).numstr(); // str = "1.2340";
| json &set_str(const sview_type s) | (1) |
|
template <typename Iterator> json &set_str(Iterator begin, const Iterator end) |
(2) |
それぞれ文字列s、null終端文字列p、[begin, end)を、UTF-8文字列と見なして自身(左辺値)にコピーします。
Version 2.112で(1)の引数をstring_typeからsview_typeに変更したことで不要になったため、const char_type *を引数に取るoverloadは削除されました。
BreakingChange2.102まではraw()という函数名でした。operator=(const string_type &)が文字列のアンエスケープ処理を行うのに対して、こちらは行わないという違いがありました。
保持している値の種類が配列 (json::array) またはオブジェクト (json::object) の時、現在の要素数を返します。
これら以外の種類の時は0を返します。
| const json &operator[](const std::size_t no) const | (1) |
| json &operator[](const std::size_t no) | (2) |
| const json &operator[](const sview_type key) const | (3) |
| json &operator[](const sview_type key) | (4) |
(1)(2) 保持している値の種類が配列かつno < size()なら、その要素への参照を返します。それ以外の時はフォールバックノードへの参照を返します。
(3)(4) 保持している値の種類がオブジェクトかつkeyという添え字の要素が存在するなら、その要素への参照を返します。それ以外の時はフォールバックノードへの参照を返します。
| json &operator()(const std::size_t no) | (1) |
| json &operator()(const sview_type key) | (2) |
(1) 保持している値の種類が配列なら、(*this)[no]への参照を返します。
no >= size()の時は、配列のサイズをno + 1に広げた上で(*this)[no]への参照を返します。
保持している値の種類が配列ではない時は、配列型に変更してから上の処理を行います。
(2) 保持している値の種類がオブジェクトなら、(*this)[key]への参照を返します。
keyという名前の要素が存在しないなら新規に作った上で参照を返します。そしてオブジェクト内部の順番リストの最後にkeyが追加されます。
保持している値の種類がオブジェクトではない時は、オブジェクト型に変更してから上の処理を行います。
| void erase(const std::size_t no) | (1) |
| void erase(const sview_type key) | (2) |
(1) 保持している値の種類が配列かつno < size()なら、(*this)[no]を削除します。
(2) 保持している値の種類がオブジェクトなら、(*this)[key]を削除します。
|
template <typename ValueType> void insert(const std::size_t no, const ValueType &right) |
(1) |
|
template <typename ValueType> void insert(const sview_type pos, const sview_type key, const ValueType &right) |
(2) |
(1) 保持している値の種類が配列かつno <= size()なら、(*this)[no]の前にrightを挿入します。
(2) 保持している値の種類がオブジェクトなら、(*this)[pos]の前にkeyを添え字とする要素を作り、そこへrightをコピーします。
オブジェクト中に既にkeyを添え字とする要素があった場合、既存のものを消した上で前述の処理を行います。posという添え字の要素がなければ何もしません。
(1)(2)とも挿入する要素の型ValueTypeは、operator=()の右辺値となりうるものなら何でも受理されます。
(1)(2) 最後の引数はversion 2.114まではconst json &型でした。
|
template <typename ValueType> void push_back(const ValueType &right) |
(1) |
|
template <typename ValueType> void push_back(const sview_type key, const ValueType &right) |
(2) |
(1) 保持している値の種類が配列なら、配列の末尾にrightを追加します。
(2) 保持している値の種類がオブジェクトなら、その末尾にkeyという添え字の要素としてrightを追加します。
既にオブジェクト中にkeyという名前の要素が存在するなら、rightで上書きした上で最後尾に移動させます。
(1)(2)とも挿入する要素の型ValueTypeは、operator=()の右辺値となりうるものなら何でも受理されます。
ctl::json js("[]"); // 配列にする。 js.push_back(1); js.push_back("a"); js.push_back(js); js.push_back(true); js.push_back(false); js.push_back(ctl::json::null); js.push_back(ctl::json::array); js.push_back(ctl::json::object); js.push_back(ctl::json::psnum(1.2, 4)); // js.stringify() == [1,"a",[1,"a"],true,false,null,[],{},1.2000]
オブジェクトに要素を新規追加する場合、通常はoperator()()による代入のほうをお使いください。このpush_back()はkeyという名前の要素が必ず最後になるような処理をする分、速度が遅めです。
ctl::json js; js("a") = 1; js("b") = 2; js("c") = 3; js("b") = 4; // 要素 "b" の再代入。 printf("%s\n", js.to_string().c_str()); // {"a":1,"b":4,"c":3} // 要素を作った順に出力される。 js.push_back("b", 5); // 要素 "b" の再代入。 printf("%s\n", js.to_string().c_str()); // {"a":1,"c":3,"b":5} // "b" は最後に回る。
(1)(2) 最後の引数はversion 2.114まではconst json &型でした。
| json allkeys() const | (1) (2.113以降) |
| void allkeys(json &out) const | (2) (2.113以降) |
(1) インスタンスがオブジェクトを保持している時、要素名の一覧文字列からなる配列を返します。それ以外の時は空のjsonインスタンスを返します。
(2) インスタンスがオブジェクトを保持している時、要素名の一覧文字列からなる配列をoutにセットします。それ以外の時はoutはclearされます。
ctl::json js; js("ab") = 1; js("cd") = 2; js("ef") = 3; ctl::json keylist = js.allkeys(); // keylist.type() == json::array // keylist.size() == 3 // keylist[0].str() == "ab" // keylist[1].str() == "cd" // keylist[2].str() == "ef" std::string json = keylist.stringify(); // ["ab","cd","ef"]
インスタンスの中身を空の配列にします。
js.empty_array()は、js.parse("[]");と等価です。
インスタンスの中身を空のオブジェクトにします。
js.empty_object()は、js.parse("{}");と等価です。
保持している値の種類をboolean型にし、値をbにします。
保持している値をnullにします。
psnum (Precision-Specified-NUMber) はset_num()を使わずoperator=()により数値を精度指定付きで代入できるようにするための補助クラスです。
このクラスには次のような2つの変数メンバとコンストラクタのみがあります。
double value;int precision;psnum(double d, int p) : value(d), precision(p) {}次のように使います。
ctl::json js;
js = ctl::json::psnum(0.123, 6);
// js.stringify() == "0.123000"
json_error型のインスタンスをparse()に引数として渡すと、パーズ中に発生したエラーの位置とその理由を受け取ることができます。
このjson_errorクラスには次のメンバ函数があります。
ctl::json_error::code_type code()std::size_t position()
code_typeの値には次のものがあります。
| code_type | 意味 |
|---|---|
| ec_ok
ec_no_error |
エラー無し。どちらも値は0です。 |
| ec_array | 配列のパーズ中にエラー。']'がない。 |
| ec_object | オブジェクトのパーズ中にエラー。'}'がない。 |
| ec_object_name | オブジェクト名のパーズ中にエラー。 |
| ec_no_colon | オブジェクト名の後ろに':'がない。 |
| ec_string | 文字列のパーズ中にエラー。閉じ'"'がない。( ctl::wjsonとctl::u16json限定)UTF-16に変換できない箇所がある。
|
| ec_number | 不正な数値表現。 |
| ec_literal | 未知のリテラル。 |
ctl::json_error e; ctl::json js; js.parse("123", e); // 戻り値はtrue. // e.code(), e.position() ともに0. js.parse("123E+", e); // 戻り値はfalse. // e.code() は ctl::json_error::ec_number, e.position() は5.
ctl::json/ctl::u8json固有の例外というものはありません。内部でnewが失敗するとstd::bad_allocが投げられるのみです。
当ライブラリ既定のnamespaceはctlですが、あらかじめ#define NAMESPACE_CTLJSON ~を定義しておくことにより変更することも出来ます。