2012/11/05

Recent entries from same category

  1. C言語から分かりやすいAPIで扱える JSON パーサ「cJSON」
  2. C++ で STL フレンドリに扱えるJSONパーサ「json.hpp」
  3. SSE を使わなくても HTML エスケープはある程度速くできる。
  4. glib を使ったマイクロフレームワーク「balde」
  5. ODBC 接続なアプリケーションの開発が楽になる C++ ライブラリ nanodbc

前回は JSMN というのを試したけど、今度も matsuu さんのブクマから。。。
parson

Lightweight json parser and reader written in C.

http://kgabis.github.com/parson/
特徴は
  • 軽い (2ファイルだけ)
  • 単純なAPI
  • ドット記法による json 値のアドレッシング (C言語の構造体やOO言語のオブジェクトに似た感じ。例: "objectA.objectB.value")
  • C89 コンパティブル
  • テストスーツ
前回の JSMN とは違い、メモリを動的に確保するタイプ。DOM の様にルートノードから探索を始め、最終的にルートノードを指定してメモリを開放する。
今回もtwitterのタイムラインをパースしよう。
#include <assert.h>
#include <string.h>
#include <memory.h>
#include <curl/curl.h>
#include "parson.h"

typedef struct {
  char* data;   // response data from server
  size_t size;  // response size of data
} MEMFILE;

MEMFILE*
memfopen() {
  MEMFILE* mf = (MEMFILE*) malloc(sizeof(MEMFILE));
  if (mf) {
    mf->data = NULL;
    mf->size = 0;
  }
  return mf;
}

void
memfclose(MEMFILE* mf) {
  if (mf->data) free(mf->data);
  free(mf);
}

size_t
memfwrite(char* ptr, size_t size, size_t nmemb, void* stream) {
  MEMFILE* mf = (MEMFILE*) stream;
  int block = size * nmemb;
  if (!mf) return block; // through
  if (!mf->data)
    mf->data = (char*) malloc(block);
  else
    mf->data = (char*) realloc(mf->data, mf->size + block);
  if (mf->data) {
    memcpy(mf->data + mf->size, ptr, block);
    mf->size += block;
  }
  return block;
}

char*
memfstrdup(MEMFILE* mf) {
  char* buf;
  if (mf->size == 0return NULL;
  buf = (char*) malloc(mf->size + 1);
  memcpy(buf, mf->data, mf->size);
  buf[mf->size] = 0;
  return buf;
}

int
main() {
  CURL* curl;
  MEMFILE* mf = NULL;
  char* js = NULL;
  int i;

  mf = memfopen();

  curl = curl_easy_init();
  curl_easy_setopt(curl, CURLOPT_URL, "http://api.twitter.com/1/statuses/user_timeline.json?screen_name=otsune");
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf);
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite);
  curl_easy_perform(curl);
  curl_easy_cleanup(curl);

  js = memfstrdup(mf);
  memfclose(mf);

  JSON_Value *root_value = json_parse_string(js);
  JSON_Array *tweets = json_value_get_array(root_value);
  for (i = 0; i < json_array_get_count(tweets); i++) {
    JSON_Object *tweet = json_array_get_object(tweets, i);
    printf("%s%s\n",
      json_object_dotget_string(tweet, "user.screen_name"),
      json_object_dotget_string(tweet, "text"));
  }

  json_value_free(root_value);
  free(js);
}
なにこれ!めちゃ簡単。しかもソースを見たところユニコードに対応してる。そしてドット演算子、良いすね。JSON XPath の様ですね。ただ残念ながら JSON XPath の様に .. でスキップする機能は無かったですが。

しかしながらこれC言語の JSON パーサの中では、私が知る限り一番扱いやすいと思いますね。(C++は別です)
MIT ライセンスなのでプロジェクトでも使って行きたいと思います。

blog comments powered by Disqus