flashでJSONを使う

普通にJSON.as(ActionScript3じゃないほう)使うだけでJSONが使えます。mtascの場合だと、JSON.asをJSON利用コードと同じディレクトリに配置して、

var json_str:String = JSON.parse( '{"foo":"foo_text"}' );
var o:Object = JSON.parse( json_str );
log( o.foo  );

というように使う。
(個人的に)問題はサーバー間通信時で、割と複雑なデータをflashでサーバー間通信する場合、普通はXMLなんですかね?よくわからないけどぱっと見た感じそんな感じを受け、JSON使うのにXMLで包むのもどうかと思ったのでFlashのLoadVarsオブジェクトを使って通信してみることにしました(結局包むことには変わりないけど)。LoadVarsではcontent typeが'application/x-www-form-urlencoded'でBODYがfoo=val1&bar=val2baz=val3な感じのレスポンスをLoadVarsのonLoadハンドラ内で扱うことができる。
今Catslyst使って遊んでるので、Catalyst::View::JSONに以下のようなパッチを当てて、

tkoyachi:~/lib/perl tkoyachi$ diff -u Catalyst-View-JSON-0.09/lib/Catalyst/View/JSON.pm Catalyst/View/JSON.pm
--- Catalyst-View-JSON-0.09/lib/Catalyst/View/JSON.pm   2006-04-20 22:17:54.000000000 +0900
+++ Catalyst/View/JSON.pm       2006-05-24 05:30:29.000000000 +0900
@@ -1,12 +1,13 @@
 package Catalyst::View::JSON;
 
 use strict;
-our $VERSION = '0.09';
+our $VERSION = '0.09a';
 
 use base qw( Catalyst::View );
 use Encode ();
 use NEXT;
 use Catalyst::Exception;
+use URI::Escape;
 
 __PACKAGE__->mk_accessors(qw( allow_callback callback_param expose_stash encoding json_dumper ));
 
@@ -86,17 +87,23 @@
         $json = Encode::encode($encoding, $json);
     }
 
-    if (($c->req->user_agent || '') =~ /Opera/) {
-        $c->res->content_type("application/x-javascript; charset=$encoding");
-    } else {
-        $c->res->content_type("text/javascript; charset=$encoding");
-    }
-
     my $output;
     $output .= "$cb(" if $cb;
     $output .= $json;
     $output .= ");"   if $cb;
 
+    if ( $c->req->args->[0]->{flashvars} ) {
+        my $flashvars = $c->req->args->[0]->{flashvars};
+        $c->res->content_type( 'application/x-www-form-urlencoded' );
+        $output = $flashvars.'='.uri_escape( $output );
+    }
+    else {
+        if (($c->req->user_agent || '') =~ /Opera/) {
+            $c->res->content_type("application/x-javascript; charset=$encoding");
+        } else {
+            $c->res->content_type("text/javascript; charset=$encoding");
+        }
+    }
     $c->res->output($output);
 }

以下のようにforwardする。forward時に渡してる第二引数はLoadVarsのonLoadハンドラ内でJSONパーサに渡すためのパラメタ名です。以下の場合だとflash側にはparams='{"foo":$foo_value}'がわたるはず。

$c->stash->{foo} = $foo_value;
$c->forward( 'MyApp::View::JSON', [{flashvars => 'params'}] );

flash側では、

var loader:LoadVars = new LoadVars();
loader.onLoad = function( success ) {
  if ( success ) {
    var result:Object = JSON.parse( this.params );
    self.log( result );
  }
  else {
    self.log( "onload error." );
  }
}
loader.load( "http://localhost:3000/get_foo" );

な感じで。