cJSON
ANSI Cで書かれた、きわめて軽量なJSONパーサーです。
目次
ライセンス
MIT ライセンス
原文MIT通知を以下に保持しています。日本語参考訳はライセンスページを参照してください。
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
使い方
cJSONへようこそ
cJSONは、必要な仕事をこなせる限り、できるだけ単純なパーサーを目指しています。Cのソースファイル1個とヘッダーファイル1個で構成されています。
JSONについては http://www.json.org/ の説明が最も適しています。XMLに似ていますが、余分なものをそぎ落としています。データの受け渡しや保存、あるいはプログラムの状態を表すために使います。
ライブラリとしてのcJSONは、できるだけ手間を減らしつつ、使い手の邪魔にならないことを目指しています。実用上の話として(厳密さはさておき)、自動と手動の2つのモードで使える、と言っておきましょう。簡単に見ていきます。
このページからJSONの例を借りてきました: http://www.json.org/fatfree.html 。そのページに触発され、JSONそのものと同じ考え方を共有しようとするパーサー、cJSONを書きました。簡単で単純、そして邪魔にならないものです。
ビルド
cJSONをプロジェクトに組み込む方法はいくつかあります。
ソースのコピー
ライブラリ全体がCファイル1個とヘッダーファイル1個だけなので、cJSON.hとcJSON.cをプロジェクトのソースへコピーするだけで使い始められます。
できるだけ多くのプラットフォームとコンパイラーに対応するため、cJSONはANSI C(C89)で書かれています。
CMake
CMakeを使うと、cJSONの本格的なビルドシステムを利用でき、最も多くの機能が使えます。CMakeは2.8.5以降に対応しています。CMakeでは、コンパイルしたファイルをソースとは別のディレクトリに置く、ソースツリー外でのビルドを推奨します。Unix環境でCMakeを使ってcJSONをビルドするには、buildディレクトリを作成し、その中でCMakeを実行します。
mkdir build
cd build
cmake ..
これでMakefileなどのファイルが作成されます。続いてコンパイルできます。
make
必要ならmake installでインストールできます。既定では、ヘッダーは/usr/local/include/cjsonに、ライブラリは/usr/local/libにインストールされます。また、既存のCMakeのインストールを検出して使用しやすくするためのpkg-config用ファイルもインストールします。さらに、CMakeを使う他のプロジェクトからライブラリを見つけられるよう、CMake設定ファイルもインストールします。
CMakeに渡す次のオプションでビルド手順を変更できます。有効にするにはOn、無効にするにはOffを指定します。
-DENABLE_CJSON_TEST=On: テストのビルドを有効にします。(既定で有効)-DENABLE_CJSON_UTILS=On: cJSON_Utilsのビルドを有効にします。(既定で無効)-DENABLE_TARGET_EXPORT=On: CMakeターゲットのエクスポートを有効にします。問題が起きる場合は無効にしてください。(既定で有効)-DENABLE_CUSTOM_COMPILER_FLAGS=On: 独自のコンパイラーフラグを有効にします。現在はClang、GCC、MSVCが対象です。問題が起きる場合は無効にしてください。(既定で有効)-DENABLE_VALGRIND=On: valgrindを使ってテストを実行します。(既定で無効)-DENABLE_SANITIZERS=On: 可能であればAddressSanitizerとUndefinedBehaviorSanitizerを有効にしてcJSONをコンパイルします。(既定で無効)-DENABLE_SAFE_STACK: SafeStackによる計装処理を有効にします。現在はClangコンパイラーでのみ動作します。(既定で無効)-DBUILD_SHARED_LIBS=On: 共有ライブラリをビルドします。(既定で有効)-DBUILD_SHARED_AND_STATIC_LIBS=On: 共有ライブラリと静的ライブラリの両方をビルドします。(既定で無効)-DCMAKE_INSTALL_PREFIX=/usr: インストール先のプレフィックスを設定します。-DENABLE_LOCALES=On: localeconvメソッドの使用を有効にします。(既定で有効)-DCJSON_OVERRIDE_BUILD_SHARED_LIBS=On:-DCJSON_BUILD_SHARED_LIBSによるBUILD_SHARED_LIBSの値の上書きを有効にします。-DENABLE_CJSON_VERSION_SO: cJSONのsoバージョンを有効にします。(既定で有効)
Linuxディストリビューション向けにcJSONをパッケージ化する場合は、例えば次の手順を使うでしょう。
mkdir build
cd build
cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off -DCMAKE_INSTALL_PREFIX=/usr
make
make DESTDIR=$pkgdir install
Windowsでは通常、Visual Studioの開発者コマンドプロンプト内でCMakeを実行し、Visual Studioソリューションファイルを作成します。具体的な手順はCMakeとMicrosoftの公式文書を参照し、好みの検索エンジンで調べてください。上記オプションの説明は概ね当てはまりますが、すべてがWindowsで動くわけではありません。
Makefile
注意: この方法は非推奨です。可能な限りCMakeを使ってください。Makefileのサポートは不具合修正に限られます。
CMakeがなくてもGNU makeがあれば、Makefileを使ってcJSONをビルドできます。
ソースコードのディレクトリでこのコマンドを実行すると、静的・共有ライブラリと小さなテストプログラムが自動的にコンパイルされます。完全なテストスイートではありません。
make all
必要ならmake installでコンパイル済みライブラリをシステムにインストールできます。既定では、ヘッダーは/usr/local/include/cjson、ライブラリは/usr/local/libにインストールされます。PREFIXとDESTDIR変数を設定すれば、この動作を変更できます: make PREFIX=/usr DESTDIR=temp install。アンインストールにはmake PREFIX=/usr DESTDIR=temp uninstallを使います。
Meson
Mesonを使うプロジェクトでcjsonを利用するには、libcjsonへの依存関係を組み込む必要があります。
project('c-json-example', 'c')
cjson = dependency('libcjson')
example = executable(
'example',
'example.c',
dependencies: [cjson],
)
Vcpkg
依存関係マネージャーvcpkgを使ってcJSONをダウンロードし、インストールできます。
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install cjson
vcpkgのcJSONポートは、Microsoftのチームメンバーとコミュニティの貢献者が最新の状態に保っています。バージョンが古い場合は、vcpkgリポジトリでIssueまたはプルリクエストを作成してください。
cJSONのインクルード
CMakeまたはMakefileでインストールした場合は、次のようにcJSONをインクルードできます。
#include <cjson/cJSON.h>
データ構造
cJSONは、cJSON構造体型を使ってJSONデータを表します。
/* The cJSON structure: */
typedef struct cJSON
{
struct cJSON *next;
struct cJSON *prev;
struct cJSON *child;
int type;
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
double valuedouble;
char *string;
} cJSON;
この型の要素はJSONの値を表します。型はtypeにビットフラグとして格納されます。(つまり、typeの値を単純に比較するだけでは型を判定できません。)
要素の型を調べるには、対応するcJSON_Is...関数を使います。この関数はNULLチェックの後に型をチェックし、要素がその型かどうかを真偽値で返します。
型には次のいずれかを使用できます。
cJSON_Invalid(cJSON_IsInvalidで確認): 値を持たない無効な要素を表します。要素の全バイトをゼロにすると、自動的にこの型になります。cJSON_False(cJSON_IsFalseで確認): 真偽値falseを表します。真偽値全般の確認にはcJSON_IsBoolも使えます。cJSON_True(cJSON_IsTrueで確認): 真偽値trueを表します。真偽値全般の確認にはcJSON_IsBoolも使えます。cJSON_NULL(cJSON_IsNullで確認):null値を表します。cJSON_Number(cJSON_IsNumberで確認): 数値を表します。値はvaluedoubleにdoubleとして格納され、valueintにも格納されます。整数の範囲を超える場合、valueintにはINT_MAXまたはINT_MINが使われます。cJSON_String(cJSON_IsStringで確認): 文字列を表します。ゼロ終端文字列の形でvaluestringに格納されます。cJSON_Array(cJSON_IsArrayで確認): 配列を表します。childが配列の値を表すcJSON要素の連結リストを指すことで実装されています。要素はnextとprevでつながれ、先頭要素はprev.next == NULL、末尾要素はnext == NULLとなります。cJSON_Object(cJSON_IsObjectで確認): オブジェクトを表します。配列と同じ方法で格納されますが、要素がキーをstringに格納する点だけが異なります。cJSON_Raw(cJSON_IsRawで確認):valuestringにゼロ終端の文字配列として格納された、任意のJSONを表します。例えば、同じ静的JSONを何度も出力するのを避けて性能を高めるために使えます。cJSONは解析時にこの型を生成することはありません。また、有効なJSONかどうかのチェックも行いません。
さらに、次の2つのフラグがあります。
cJSON_IsReference:childが指す要素、またはvaluestring、あるいはその両方を、この要素が所有していないことを示します。これらは参照にすぎません。そのためcJSON_Deleteなどの関数は、この要素だけを解放し、childやvaluestringは解放しません。cJSON_StringIsConst:stringが定数文字列を指していることを意味します。cJSON_Deleteなどの関数はstringを解放しようとしません。
データ構造の操作
値の型ごとに、その型の要素を作成するcJSON_Create...関数があります。これらの関数はすべて、後からcJSON_Deleteで削除できるcJSON構造体を割り当てます。いずれかの時点で削除しなければ、メモリーリークが起きることに注意してください。
重要: 要素をすでに配列やオブジェクトに追加した場合、その要素をcJSON_Deleteで削除してはいけません。追加によって所有権が移り、配列やオブジェクトが削除される際に、その要素も削除されます。cJSON_SetValuestringでcJSON_Stringのvaluestringを変更することもでき、その場合は以前のvaluestringを手動で解放する必要はありません。
基本型
- nullは
cJSON_CreateNullで作成します。 - 真偽値は
cJSON_CreateTrue、cJSON_CreateFalseまたはcJSON_CreateBoolで作成します。 - 数値は
cJSON_CreateNumberで作成します。valuedoubleとvalueintの両方が設定されます。整数の範囲を超える場合、valueintにはINT_MAXまたはINT_MINが使われます。 - 文字列は
cJSON_CreateString(文字列をコピー)またはcJSON_CreateStringReference(文字列を直接参照)で作成します。後者ではcJSON_Deleteでvaluestringが削除されず、その寿命の管理は利用者の責任となります。定数に便利です。
配列
空の配列はcJSON_CreateArrayで作成できます。cJSON_CreateArrayReferenceは、内容を「所有」しない配列を作成するために使えます。その内容はcJSON_Deleteで削除されません。
配列の末尾に要素を追加するにはcJSON_AddItemToArrayを使います。cJSON_AddItemReferenceToArrayを使うと、別の要素、配列、文字列への参照として要素を追加できます。この場合、cJSON_Deleteはその要素のchildやvaluestringを削除しないので、別の場所ですでに使われていても二重解放は起きません。途中に挿入するにはcJSON_InsertItemInArrayを使います。指定した0始まりのインデックスに要素を挿入し、既存の要素をすべて右に移動します。
指定したインデックスの要素を配列から取り出し、そのまま使い続けるにはcJSON_DetachItemFromArrayを使います。取り外した要素を返すので、必ずポインターに代入してください。そうしないとメモリーリークが起きます。
要素を削除するにはcJSON_DeleteItemFromArrayを使います。cJSON_DetachItemFromArrayと同じように動作しますが、取り外した要素をcJSON_Deleteで削除します。
配列の要素をその場で置き換えることもできます。インデックスを指定するcJSON_ReplaceItemInArray、または要素へのポインターを渡すcJSON_ReplaceItemViaPointerを使います。cJSON_ReplaceItemViaPointerは失敗すると0を返します。内部では古い要素を取り外して削除し、新しい要素をその位置に挿入します。
配列の大きさを得るにはcJSON_GetArraySizeを使います。指定したインデックスの要素を得るにはcJSON_GetArrayItemを使います。
配列は連結リストとして格納されるため、インデックスによる反復は効率が悪く、計算量はO(n²)になります。cJSON_ArrayForEachマクロを使えばO(n)で反復できます。
オブジェクト
空のオブジェクトはcJSON_CreateObjectで作成できます。cJSON_CreateObjectReferenceは、内容を「所有」しないオブジェクトを作成するために使えます。その内容はcJSON_Deleteで削除されません。
オブジェクトに要素を追加するにはcJSON_AddItemToObjectを使います。名前(要素のキー、つまりcJSON構造体のstring)が定数または参照である要素を追加するにはcJSON_AddItemToObjectCSを使います。これにより、その名前はcJSON_Deleteで解放されなくなります。cJSON_AddItemReferenceToArrayを使うと、別のオブジェクト、配列、文字列への参照として要素を追加できます。この場合、cJSON_Deleteはその要素のchildやvaluestringを削除しないので、別の場所ですでに使われていても二重解放は起きません。
要素をオブジェクトから取り出し、そのまま使い続けるにはcJSON_DetachItemFromObjectCaseSensitiveを使います。取り外した要素を返すので、必ずポインターに代入してください。そうしないとメモリーリークが起きます。
要素を削除するにはcJSON_DeleteItemFromObjectCaseSensitiveを使います。cJSON_DetachItemFromObjectCaseSensitiveの後にcJSON_Deleteを呼ぶのと同じように動作します。
オブジェクトの要素をその場で置き換えることもできます。キーを指定するcJSON_ReplaceItemInObjectCaseSensitive、または要素へのポインターを渡すcJSON_ReplaceItemViaPointerを使います。cJSON_ReplaceItemViaPointerは失敗すると0を返します。内部では古い要素を取り外して削除し、新しい要素をその位置に挿入します。
オブジェクトの大きさを得るにはcJSON_GetArraySizeを使えます。内部ではオブジェクトも配列として格納されているためです。
オブジェクトの要素にアクセスするにはcJSON_GetObjectItemCaseSensitiveを使います。
オブジェクトを反復するには、配列と同じ方法でcJSON_ArrayForEachマクロを使えます。
cJSONには、cJSON_AddNullToObjectなど、新しい要素を作成してオブジェクトに追加する便利な補助関数もあります。新しい要素へのポインターを返し、失敗するとNULLを返します。
JSONの解析
ゼロ終端文字列に入ったJSONは、cJSON_Parseで解析できます。
cJSON *json = cJSON_Parse(string);
ゼロ終端かどうかにかかわらず、文字列に入ったJSONはcJSON_ParseWithLengthで解析できます。
cJSON *json = cJSON_ParseWithLength(string, buffer_length);
JSONを解析し、それを表すcJSON要素の木を割り当てます。関数が戻った後、使い終わった木をcJSON_Deleteで解放する責任は、すべて利用者にあります。
cJSON_Parseが使うアロケーターは、既定ではmallocとfreeですが、cJSON_InitHooksでグローバルに変更できます。
エラーが起きた場合、入力文字列内のエラー位置へのポインターをcJSON_GetErrorPtrで取得できます。ただし、マルチスレッド環境では競合状態を引き起こす可能性があるため、その場合はreturn_parse_endを指定してcJSON_ParseWithOptsを使うほうがよいでしょう。既定では、解析されたJSONの後に入力文字列中の文字が残っていてもエラーとはみなしません。
さらにオプションが必要なら、cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)を使います。return_parse_endは入力文字列中のJSONの終端、またはエラー位置へのポインターを返します。これにより、スレッドセーフな方法でcJSON_GetErrorPtrを置き換えられます。require_null_terminatedを1に設定すると、入力文字列にJSONの後のデータがある場合はエラーになります。
バッファー長を指定するオプションも必要なら、cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)を使います。
JSONの出力
cJSON要素の木があれば、cJSON_Printで文字列として出力できます。
char *string = cJSON_Print(json);
文字列を割り当て、木のJSON表現を書き込みます。関数が戻った後、使い終わった文字列を自身のアロケーターで解放する責任は、すべて利用者にあります。通常はfreeですが、cJSON_InitHooksで何を設定したかによって異なります。
cJSON_Printは整形用の空白を入れて出力します。整形せずに出力するにはcJSON_PrintUnformattedを使います。
出力する文字列のおおよその大きさが分かる場合は、cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)を使えます。fmtは空白による整形を有効・無効にする真偽値です。prebufferは最初のバッファーの大きさを指定します。cJSON_Printでは現在、最初のバッファーに256バイトを使います。出力中に空きがなくなると新しいバッファーを割り当て、古い内容をコピーしてから出力を続けます。
この動的なバッファー割り当ては、cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)で完全に避けられます。書き込み先バッファーへのポインターと、その長さを渡します。長さの限界に達すると出力に失敗して0を返し、成功すると1を返します。ただし、メモリーの容量が十分かどうかの見積もりは完全には正確でないため、実際に必要な量より5バイト多く用意してください。
例
この例では、次のJSONを作成し、解析します。
{
"name": "Awesome 4K",
"resolutions": [
{
"width": 1280,
"height": 720
},
{
"width": 1920,
"height": 1080
},
{
"width": 3840,
"height": 2160
}
]
}
出力
上のJSONを作成し、文字列として出力してみましょう。
//create a monitor with a list of supported resolutions
//NOTE: Returns a heap allocated string, you are required to free it after use.
char *create_monitor(void)
{
const unsigned int resolution_numbers[3][2] = {
{1280, 720},
{1920, 1080},
{3840, 2160}
};
char *string = NULL;
cJSON *name = NULL;
cJSON *resolutions = NULL;
cJSON *resolution = NULL;
cJSON *width = NULL;
cJSON *height = NULL;
size_t index = 0;
cJSON *monitor = cJSON_CreateObject();
if (monitor == NULL)
{
goto end;
}
name = cJSON_CreateString("Awesome 4K");
if (name == NULL)
{
goto end;
}
/* after creation was successful, immediately add it to the monitor,
* thereby transferring ownership of the pointer to it */
cJSON_AddItemToObject(monitor, "name", name);
resolutions = cJSON_CreateArray();
if (resolutions == NULL)
{
goto end;
}
cJSON_AddItemToObject(monitor, "resolutions", resolutions);
for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
{
resolution = cJSON_CreateObject();
if (resolution == NULL)
{
goto end;
}
cJSON_AddItemToArray(resolutions, resolution);
width = cJSON_CreateNumber(resolution_numbers[index][0]);
if (width == NULL)
{
goto end;
}
cJSON_AddItemToObject(resolution, "width", width);
height = cJSON_CreateNumber(resolution_numbers[index][1]);
if (height == NULL)
{
goto end;
}
cJSON_AddItemToObject(resolution, "height", height);
}
string = cJSON_Print(monitor);
if (string == NULL)
{
fprintf(stderr, "Failed to print monitor.\n");
}
end:
cJSON_Delete(monitor);
return string;
}
別の方法として、cJSON_Add...ToObject補助関数を使えば、少し楽になります。
//NOTE: Returns a heap allocated string, you are required to free it after use.
char *create_monitor_with_helpers(void)
{
const unsigned int resolution_numbers[3][2] = {
{1280, 720},
{1920, 1080},
{3840, 2160}
};
char *string = NULL;
cJSON *resolutions = NULL;
size_t index = 0;
cJSON *monitor = cJSON_CreateObject();
if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL)
{
goto end;
}
resolutions = cJSON_AddArrayToObject(monitor, "resolutions");
if (resolutions == NULL)
{
goto end;
}
for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
{
cJSON *resolution = cJSON_CreateObject();
if (cJSON_AddNumberToObject(resolution, "width", resolution_numbers[index][0]) == NULL)
{
goto end;
}
if (cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL)
{
goto end;
}
cJSON_AddItemToArray(resolutions, resolution);
}
string = cJSON_Print(monitor);
if (string == NULL)
{
fprintf(stderr, "Failed to print monitor.\n");
}
end:
cJSON_Delete(monitor);
return string;
}
解析
この例では、上の形式のJSONを解析し、診断情報を出力しながら、モニターがFull HDの解像度に対応しているか調べます。
/* return 1 if the monitor supports full hd, 0 otherwise */
int supports_full_hd(const char * const monitor)
{
const cJSON *resolution = NULL;
const cJSON *resolutions = NULL;
const cJSON *name = NULL;
int status = 0;
cJSON *monitor_json = cJSON_Parse(monitor);
if (monitor_json == NULL)
{
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL)
{
fprintf(stderr, "Error before: %s\n", error_ptr);
}
status = 0;
goto end;
}
name = cJSON_GetObjectItemCaseSensitive(monitor_json, "name");
if (cJSON_IsString(name) && (name->valuestring != NULL))
{
printf("Checking monitor \"%s\"\n", name->valuestring);
}
resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions");
cJSON_ArrayForEach(resolution, resolutions)
{
cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width");
cJSON *height = cJSON_GetObjectItemCaseSensitive(resolution, "height");
if (!cJSON_IsNumber(width) || !cJSON_IsNumber(height))
{
status = 0;
goto end;
}
if ((width->valuedouble == 1920) && (height->valuedouble == 1080))
{
status = 1;
goto end;
}
}
end:
cJSON_Delete(monitor_json);
return status;
}
cJSON_Parseの結果以外にはNULLチェックがないことに注意してください。cJSON_GetObjectItemCaseSensitiveがすでにNULL入力をチェックしているため、NULL値はそのまま伝播し、入力がNULLならcJSON_IsNumberとcJSON_IsStringは0を返します。
注意事項
ゼロ文字
cJSONは、ゼロ文字'\0'または\u0000を含む文字列には対応していません。文字列がゼロ終端であるため、現在のAPIでは扱えません。
文字エンコーディング
cJSONはUTF-8でエンコードされた入力にのみ対応しています。ただし、無効なUTF-8入力も、多くの場合は拒否せずそのまま伝播します。入力に無効なUTF-8が含まれていない限り、出力は常に有効なUTF-8になります。
C規格
cJSONはANSI C(C89、C90とも呼ばれます)で書かれています。コンパイラーやCライブラリがこの規格に従っていない場合、正しい動作は保証されません。
注意: ANSI CはC++ではないので、C++コンパイラーでコンパイルするべきではありません。ただし、CコンパイラーでコンパイルしてC++コードとリンクすることはできます。C++コンパイラーでコンパイルして動く場合もありますが、正しい動作は保証されません。
浮動小数点数
cJSONは、IEEE754倍精度浮動小数点数以外のdouble実装を公式にはサポートしていません。他の実装でも動く可能性はありますが、それらで起きた不具合は無効な報告とみなされます。
cJSONが対応する浮動小数点リテラルの長さは、現在、最大63文字です。
配列とオブジェクトの深い入れ子
配列やオブジェクトが深く入れ子になっているとスタックオーバーフローが起きるため、cJSONは深すぎる入れ子に対応していません。これを防ぐため、深さをCJSON_NESTING_LIMITで制限しています。既定値は1000で、コンパイル時に変更できます。
スレッド安全性
一般に、cJSONはスレッドセーフではありません。
ただし、次の条件を満たす場合はスレッドセーフです。
cJSON_GetErrorPtrを一切使わないこと。代わりにcJSON_ParseWithOptsのreturn_parse_endパラメーターを使えます。cJSON_InitHooksを呼ぶのは、いずれのスレッドでもcJSONを使い始める前だけであること。- cJSON関数のすべての呼び出しが戻るまでは、
setlocaleを一切呼ばないこと。
大文字と小文字の区別
cJSONは当初、JSON規格に従わず、大文字と小文字を区別していませんでした。規格に準拠した正しい動作が必要なら、利用できる箇所ではCaseSensitive関数を使ってください。
オブジェクトの重複メンバー
cJSONは、同じ名前のメンバーが複数あるオブジェクトを含むJSONの解析と出力に対応しています。ただし、cJSON_GetObjectItemCaseSensitiveは常に最初の1つだけを返します。
cJSONをお楽しみください!
- Dave Gamble(原作者)
- Max BrucknerとAlan Wang(現在のメンテナー)
- その他のcJSONの貢献者