PerlでJSONPデータを処理する方法

PerlでJSONPデータを処理する方法

Posted at June 15,2012 1:23 AM
Tag:[JSON, JSONP, Perl]

PerlでJSONデータ・JSONPデータを処理する方法です。

1.JSONデータを処理する

JSONPデータの処理を解説する前に、JSONデータの処理について簡単に紹介します。

外部APIを起動し、次のようなJSONデータを受信したと想定します。

[
  {
    'link' => 'http://user-domain/aaa.html',
    'title' => "テスト1"
  },
  {
    'link' => 'http://user-domain/bbb.html',
    'title' => "テスト2"
  },
  {
    'link' => 'http://user-domain/ccc.html',
    'title' => "テスト3"
  }
];

この受信データの場合、次のようにJSONモジュールを利用することでPerlで処理できるようになります。

#!/usr/bin/perl
use strict;
use warnings;
 
use CGI;
use JSON;
use LWP::UserAgent;
 
my $q = new CGI;
print $q->header( -charset => "utf-8" );
 
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new( GET => '外部APIのURL' );
my $res = $ua->request( $req );
 
# $res->contentにJSONデータ
my $data = from_json( $res->content );
foreach (@{$data}) {
    print $_->{ link };
    print $_->{ title };
}

下のコードによる実装も可能です。他にもあるようですがここでは割愛します。

my $json = new JSON;
my $perl_scalar = $json->decode($json_text);

2.JSONPデータを処理する

本題はここからで、まず、はてなブックマークの人気エントリー取得用APIに「json」をつけて起動するとJSONデータを取得できるという情報がありました。

http://b.hatena.ne.jp/entrylist/json?url=http%3A%2F%2Fwww.koikikukan.com%2F&sort=count

が、実際には次のようなJSONPデータが返却されてしまいます(API起動方法が間違っていたらすいません)。データの一部は省略しています。

([
  {
    'link' => 'http://user-domain/aaa.html',
    'title' => "テスト1"
  },
  {
    'link' => 'http://user-domain/bbb.html',
    'title' => "テスト2"
  },
  {
    'link' => 'http://user-domain/ccc.html',
    'title' => "テスト3"
  }
]);

ということで、JSONPをPerlで処理する方法が必要になりました。

JSONデータをPerlで処理するには、1項のJSONやJSON:Syckなどが用意されていますが、JSONPについてはサーバ処理(JSONPデータを返却する処理)はありましたが、クライアントとして処理するモジュールやサンプルがみつけらませんでした。

よって力技ですが、次のようにJSONPデータにある先頭と末尾のカッコを除去して、JSONデータに変換してからJSONモジュールで処理してみました(赤色部分)。

#!/usr/bin/perl
use strict;
use warnings;
 
use CGI;
use JSON;
use LWP::UserAgent;
 
my $q = new CGI;
print $q->header( -charset => "utf-8" );
 
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new( GET => '外部APIのURL' );
my $res = $ua->request( $req );
my $content = $res->content;
$content =~ s/^\((.*)\);$/$1/;
my $data = from_json( $content );
foreach (@{$data}) {
    print $_->{ link };
    print $_->{ title };
}

が、間違いなく適切な方法があると思ってますので、誰かが正解をつぶやかれたらこの記事を修正したいと思います。他力本願ですいません。

ちなみに、さきほどのJSONPデータを正しいJSONPとして処理したい場合は、はてなブックマークの人気エントリー取得用APIのクエリパラメータに「callback=xxx」を付与します。

<pre><code>http://b.hatena.ne.jp/entrylist/json?url=http%3A%2F%2Fwww.koikikukan.com%2F&amp;sort=count&amp;callback=foo</code></pre>

これでJSONPデータが返却されます。

foo([
  {
    'link' => 'http://user-domain/aaa.html',
    'title' => "テスト1"
  },
  {
    'link' => 'http://user-domain/bbb.html',
    'title' => "テスト2"
  },
  {
    'link' => 'http://user-domain/ccc.html',
    'title' => "テスト3"
  }
]);
関連記事
トラックバックURL


コメントする
greeting

*必須

*必須(非表示)


ご質問のコメントの回答については、内容あるいは多忙の場合、1週間以上かかる場合があります。また、すべてのご質問にはお答えできない可能性があります。予めご了承ください。

太字イタリックアンダーラインハイパーリンク引用
[サインインしない場合はここにCAPTCHAを表示します]

コメント投稿後にScript Errorや500エラーが表示された場合は、すぐに再送信せず、ブラウザの「戻る」ボタンで一旦エントリーのページに戻り(プレビュー画面で投稿した場合は、投稿内容をマウスコピーしてからエントリーのページに戻り)、ブラウザをリロードして投稿コメントが反映されていることを確認してください。

コメント欄に(X)HTMLタグやMTタグを記述される場合、「<」は「&lt;」、「>」は「&gt;」と入力してください。例えば「<$MTBlogURL$>」は「&lt;$MTBlogURL$&gt;」となります(全て半角文字)