2013年10月20日日曜日

json-c

設定ファイル等のデータ形式として色々と考えられますが、JSONがなかなか良いのではないかと思います。ECMA標準にもなったようです。独断と偏見でデータ形式の利点、欠点をまとめてみました。

データ形式 利点と欠点
バイナリファイル 構造体をそのまま入力すれば読み込み速度は速いし、プログラミングは楽。内容をあまり見せたくない場合には、見にくく編集もしにくいので良い。エンディアンやアライメントの違いなどCPUやコンパイラによって互換性に問題が生じることがある。またデータのバージョンアップ等で間にデータを挿入すると互換性がなくなる。
csv Microsoft Excelで簡単に作ることができる。読み込みのプログラミングも比較的楽。ただしフォーマットが曖昧。通常は小数点がドット(.)で、区切りがカンマ(,)だが、例えばドイツ語版Excelだと小数点がカンマ(,)になり、区切りがセミコロン(;)になるので注意。その他、ダブルコーテーション(")の扱いなど不明点が多い。
INI Windowsの場合、Win32APIを使用すればプログラミングが楽。階層構造が2弾(セクションとキー)しかなく、また配列の表現が出来ないため、複雑な表現はできない。
XML 汎用性が高く、表現力が高い。XPathやXSLやXML SchemaなどXMLを元にした仕様も充実している。仕様が複雑で仕様通りの読み込みのプログラムを完全に自作するのは難しい。しかしライブラリが多くあり、ツールも多い。汎用性が高すぎるために、XMLを元にしたフォーマット(スキーマ)を良い物にするにはそれなりの知識が必要。また冗長性が高いため、データサイズが大きくなる。
JSON 配列や連想配列などのプログラミングで必要な型をそのまま表現できるのが便利。仕様が非常にシンプルで、読み込みのプログラムも比較的簡単に作成できる。

JSONは読み込みのプログラミングが簡単と書きましたが、動的な文字列や連想配列を扱う言語でないと少し厄介かもしれません。やはりライブラリがあれば便利です。

C言語でいくつかライブラリがありますが、 Fedoraではインストーラの段階でjson-cとjson-glibが入っていました。中でもjson-cは依存関係が少なくWindowsでも使用できるなど使い勝手が良さそうなので使ってみました。

json-cの開発環境は以下でインストールできます。

$ sudo yum install json-c-devel

テストプログラムは以下です。jsontest.jsonを読み込み、表示するだけのプログラムですが、これだけの関数が使えれば読み込みは十分だと思われます。

jsontest.c

#include <stdio.h>
#include <json/json.h>

int json_print(json_object *obj)
{
        json_type jt;
        int len, i;
        
        jt = json_object_get_type(obj);
        switch(jt) {
        case json_type_null:
                printf("null\n");
                break;
        case json_type_boolean:
                if (json_object_get_boolean(obj)) {
                        printf("true\n");
                } else {
                        printf("false\n");
                }
                break;
        case json_type_double:
                printf("%f\n", json_object_get_double(obj));
                break;
        case json_type_int:
                printf("%d\n", json_object_get_int(obj));
                break;
        case json_type_object:
                {
                        struct json_object_iterator je, ji;
                        json_object *jo;
                        const char *key;

                        ji = json_object_iter_begin(obj);
                        je = json_object_iter_end(obj);
                        printf("{\n");
                        while (!json_object_iter_equal(&ji, &je)) {
                                key = json_object_iter_peek_name(&ji);
                                printf("%s:\n", key);
                                jo = json_object_object_get(obj, key);
                                json_print(jo);
                                json_object_iter_next(&ji);
                        }
                        printf("}\n");
                }
                break;
        case json_type_array:
                len = json_object_array_length(obj);
                printf("[\n");
                for (i = 0; i < len; i++) {
                        json_object *jo;
                        jo = json_object_array_get_idx(obj, i);
                        json_print(jo);
                }
                printf("]\n");
                break;
        case json_type_string:
                printf("\"%s\"\n", json_object_get_string(obj));
                break;
        default:
                return 1;
        }
        return 0;
}


int main()
{
        json_object *jo;

        jo = json_object_from_file("jsontest.json");
        json_print(jo);
        json_object_put(jo);

        return 0;
} 

コンパイル時にはlibjson-cをリンクします。
$ gcc jsontest.c -ljson-c

注意点は以下です。
  • json_objectは参照カウンタでメモリ管理されているので、使用後にjson_object_put()でメモリを解放する必要がある。
  • json_object_array_get_idx()等の関数で得たjson_objectは参照カウンタをカウントアップしない。元のjson_objectを削除すると参照できなくなる。また得られたjson_objectをjson_object_put()すると元のデータも変更され、その部分が削除される。必要な場合はjson_object_get()でカウントアップする。
  • エラーをあまり返さない。エラー時にNULLを返すため、エラーでNULLなのか、データ自体が無くNULLなのかの判断がしにくい。
  • 文字列の文字コードはutf-8。

1 件のコメント:

  1. 私が神と非常に深く個人的な関係を持っていることは秘密ではありません。去年、ヘルペスと一緒に生活しなければならなかったすべてのでたらめを通してその関係を押して抵抗しましたが、神は私の頑固さよりも大きく、そのヘルペスと性器ヘルペスのすべてを突破しました。個人的には、自分がどれほど良くないかを何度も何度も聞くことは、可能な限り最悪の方法で私の心に侵入しました。私は完全にシャットダウンし、このように人生が一時的なヘルペスの大流行を終わらせようとしているように目を覚ましていました。
    漢方薬にノーと言うのはco病です。それは恐怖に基づいています。そして、それは私の心が望むものに対して不誠実です。自分の周りに壁を作らないでください。特に健康上の問題や治療法に関しては、ハーブが作られたり、大胆な一歩を踏み出すことを恐れています。多くの若い男性/女性が何度も何度も私に言います、イトゥア博士は私を詐欺するつもりです、しかし今日私は彼に試みを与えます私は誰も漢方薬について私を納得させないだろうと感じていますわずか2週間飲んで、私は1年と数ヶ月間住んでいますが、今はアウトブレイクを経験していません、ヘルペス、統合失調症、癌、脊柱症、線維筋痛症、フルオロキノロンなどの病気のために彼の漢方薬が必要な場合は彼に連絡できます毒性症候群線維異形成症進行性。致命的な家族性不眠症第5因子ライデン突然変異、てんかんデュピュイトラン病、線維形成、糖尿病、セリアック病、クロイツフェルト・ヤコブ、ライム病、てんかん、病気、Co病、コプシー、アルツ、骨異形成症男性/女性不妊症、腸疾患、ハンチントン病、糖尿病、子宮筋腫。疾患、ループス、リポイド蓄積症(ゴーシェ病)、多嚢胞性疾患、脳アミロイド血管障害、運動失調、肝硬変、関節炎、筋萎縮性側索硬化症、アルツハイマー病、副腎皮質癌。喘息、アレルギー、HIV、てんかん、不妊、。 Email..drituaherbalcenter@gmail.com then what app。+ 2348149277967 ....そこにいる病気の男性/女性に対する私のアドバイスは簡単です...常に開かれた本になり​​ましょう。あなた自身、あなたの状況、そしてあなたが何をしているのかについて正直にいじってください。何も遠慮しないでください。持ちこたえると、どこにも行けなくなります...たぶん、孤独なビルへの片道チケットであり、それはあなたが行きたい場所ではありません。だから私の最後の真実...そして私はこれを理解し始めたところです。

    返信削除