読者です 読者をやめる 読者になる 読者になる

hspinetでJSONをいじる

HSP プログラミング メモ

HSP3.3からhspinetにjsonを読み書きする機能が追加されました。解説があまりネット上で見つからなかったので調べて書いてみます。パースするJsonは以下のような形式です。

{
   "Data": 
   {
      "value": 3,
      "str": "Hello",
      "info": 
      [
         {"id": 1, "name": "Alice"},
         {"id": 2, "name": "Millia"}
      ]
   }
}

これをツリー構造で表すと以下のようになります。HSPのマニュアルではこのツリー構造をオブジェクトとよんでいるみたいです。つまりオブジェクトを取得するというのは全体の木のうちの一部(部分木)を取得すると読みかえられます。
f:id:ikaro1192:20120318114735p:plain

HSPでこれをパースするためにはまずJSONオブジェクトを開かなくてはいけません。

notesel JsonData
noteload "test.json"
	
//文字列からJsonオブジェクト生成
jsonopen JsonPtr,JsonData

jsonopenが実行された時点でJsonPtrにはJsonオブジェクトのRootのポインタが代入されます。どうやらこのポインタ(たぶんハンドラといったほうが近い)は自分のひとつ下の階層の要素しか参照できないようです。そこでまずRootからDataの階層に下りなくてはいけません。階層を下る(正確には部分木を得る)にはjsongetobjを利用します。

//JsonPtrにDataの階層のポインタが代入される
jsongetobj JsonPtr,"Data",JsonPtr
	
jsongeti Value,"value",JsonPtr
jsongets String,"str",JsonPtr
mes strf("Value:%d,str%s",Value,String)

Dataの階層に移動した後はvalueやstrは自分の直下の階層ということになるのでjsongetsなどを利用して値を得ます。

info以下ですがこちらは配列なので工夫が必要です。HSPではJSONの配列にインデックスでAccessする方方が提供されていないのでイテレータ的な雰囲気でwhileでまわして取得します。また、名前があるわけではないのでjsongetobjではなくjsonnextで配列以下の部分木を取得する必要があります。以下サンプル

//infoの階層に移動
jsongetobj InfoPtr,"info",JsonPtr
	
jsonnext InfoPtr,InfoPtr,2
while(InfoPtr!=NULL)	
	jsongeti ID,"id",InfoPtr
	jsongets Name,"name",InfoPtr
	mes strf("ID:%d 名前:%s",ID,Name)
        //Nextが存在しないとInfoにNULLが返る
	jsonnext InfoPtr,InfoPtr,0
wend

以上をまとめると以下のようなscriptになります。

#include "hspinet.as"

//0をNULLと定数宣言
#const NULL 0

	notesel JsonData
	noteload "test.json"
	
	//文字列からJsonオブジェクト生成
	jsonopen JsonPtr,JsonData
	
	jsongetobj JsonPtr,"Data",JsonPtr
	
	jsongeti Value,"value",JsonPtr
	jsongets String,"str",JsonPtr
	mes strf("Value:%d,str%s",Value,String)

	
	jsongetobj InfoPtr,"info",JsonPtr
	
	jsonnext InfoPtr,InfoPtr,2
	while(InfoPtr!=NULL)	
		jsongeti ID,"id",InfoPtr
		jsongets Name,"name",InfoPtr
		mes strf("ID:%d 名前:%s",ID,Name)
                //Nextが存在しないとInfoにNULLが返る
		jsonnext InfoPtr,InfoPtr,0
	wend
	
	//JSONオブジェクト開放
	jsonclose