HaxeでJsonをパースする


HaxeでJsonを扱うには、haxe.Jsonというクラスを使います。

公式 http://haxe.org/api/haxe/json を見る感じJsonクラスの持つメソッドは

static function parse( text : String ) : Dynamic
static function stringify( value : Dynamic, ?replacer : Dynamic -> Dynamic -> Dynamic ) : String

の二つみたいです。

実際に使ってみます。

json
{
    "users": [
        {
            "name": "Akeru",
            "sex": "male"
        }, {
            "name": "Amamori",
            "sex": "female"
        }]
}

というJsonを読むことにしましょう。

  

Main.hx

import haxe.Json;

class Main {

    public static function main() {
        var data : String =
            '{
                "users": [
                    {
                        "name": "Akeru",
                        "sex": "male"
                    }, {
                        "name": "Amamori",
                        "sex": "female"
                    }]
            }
        ';
        var user_datas = Json.parse(data);
        trace('user1: ${user_datas.users[0]}');
        untyped trace('user1\'s name: ${user_datas.users[0].name}');
    }
}

こんな感じになります。

次に、コンソールでhaxe -x Main.hxと打ち込みます。-xというオプションをつけることで、コンパイルしつつ即座に実行出来ます。

実行することで

Main.hx:19: user1: { name => Akeru,  sex => male }
Main.hx:20: user1's name: Akeru

という結果を得られたかと思います。

  

さて、ここで一つだけ問題があります。ソースコードに目を戻してください。
trace('user1: ${user_datas.users[0]}');
の後が
untyped trace('user1\'s name: ${user_datas.users[0].name}');
となっているかと思います。

これは${user_datas.users[0]}のアクセスの時点で、user_datas.usersがArray<String>だと型推論されてしまい、.nameメンバの呼び出しに対してコンパイラがエラーを吐いてしまうためで、untypedを使ってそれを抑制しています。

呼び出し自体には問題はないので、untypedを使ってガンガン無視していけば、もっと階層の深いJsonでも問題は出ない……と思うのですが、それだとHaxeを使うメリットが減るような気がするので、パースしたJsonを適当な構造体にマップして返してあげる関数を、それぞれ定義するような形になるのかなぁと今のところは思っています。

  

haxelibをちょっと眺めた感じmartamius/TJSONなんかは、C#でいうところのDynamicJsonめいた感じで、パパッと匿名の構造体にマッピングしてくれるようですがまだ試していないです。
標準のライブラリでも、untypedを使わないスマートなやり方やなんかがあったら教えていただけるとうれしいです。