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 ~
を定義しておくことにより変更することも出来ます。