40歳からのキャリアチェンジ

20代はエンジニア・PM、30代はWeb系エンジニア向けのキャリアアドバイザー。40代の今はフリーランスで開発含めて色々やってます。技術ネタとしてはRuby/RailsとJavaScript関連あたり

033-今度はUnable to parse JSON stringのエラーにはまる

Unable to parse JSON string

MongoDBに格納した情報を、Sinatra + mongoidでJSON形式で出力するところまでは出来たので、これを読み込むような処理をするためにこんなコードを書きました

var Blogger = function(){
  this.httpclient = Titanium.Network.createHTTPClient();
};

Blogger.prototype = {
  get:function(){
    var self = this;
    var url =  "http://localhost:4567/api/oyamada.json";
    self.httpclient.open('GET',url); // レスポンスを受け取るイベント
    self.httpclient.onload = function(){
      var entries = JSON.parse(this.responseText);
      // 以下省略
    };
    self.httpclient.send();
  }
};
var blogger = new Blogger();
blogger.get();

これを実行すると、

message = "Unable to parse JSON string";
name = SyntaxError;

というエラーが出てこの解決に思っていた以上に時間がかかったのでそのあたりまとめておきます

問題の切り分けのためにやったこと

最初は、Titanium Mobile のhttpclientの使い方を間違っているのか、それとも自分がサーバ側で生成しているJSONのフォーマットが正しくないのかを切り分けるため、

    var url =  "http://api.twitter.com/1/statuses/user_timeline.json?screen_name=h5y1m141";

としてtwitterのtimeline読み込めるか確認しました。

するとこちらは問題なくparse出来たので、自分がサーバ側で生成しているJSONフォーマットが正しくなかったようです

JSONLintを使って検証

JSONLintというサイトをたまたま見つけたので、

  • Sinatra + mongoidでJSON形式で出力
  • 出力されるデータを上記のJSONLintのフォームにコピペして検証

という作業を地道に繰り返しました。

この作業をする中で、iPhone側でJSONを読み込んだ時の処理のしやすい構造にしたほうが良いと考えるようになり、

{
  0:{
    "url":"http..",
  },
  1:{
    "url":"http.."}
  }
}

のような構造にすることを決めて、サーバ側のSinatraのコードを下記のようにしました。

get '/api/:name.json' do
  blogger = params[:name]
  body = []
  result = []

  @items = Entry.find(:conditions => {:blogger => blogger})

  @items.each_with_index do |item,i|
    content_type :json
    body.push('"' + i.to_s +  '":' + item.to_json + '')
  end
  result = '{' + body.join(',') + '}'
  result
end

もっとスマートな書き方がありそうだけど自分の現在のスキルだとこれが精一杯(苦笑)