2011-07-24 5 views
4

私はHalf Life 2サーバーの詳細を把握するために(protocol-srcdsライブラリを使用して)非常に小さなプログラムに取り組んできました。ワークフローはかなり簡単です。ファイルからサーバーのリストを取得し、それらのそれぞれに照会し、出力を別のファイルに書き出します(vBulletinと結びついているので、PHPスクリプトで表示されます)。それがSQLなどで行われていればうれしいですが、私がまだ学んでいるのを見て、それは今のところ遠すぎるステップです!HaskellでJSONを使用してレコードをシリアライズ

私の質問は、シリアル化、つまりJSONにシリアル化することに関連しています。

jsonify (Just (SRCDS.GameServerInfo serverVersion 
          serverName 
          serverMap  
          serverMod  
          serverModDesc 
          serverAppId 
          serverPlayers 
          serverMaxPlayers 
          serverBots 
          serverType 
          serverOS 
          serverPassword 
          serverSecure 
          serverGameVersioning)) = 
          toJSObject [ ("serverName", serverName) 
             , ("serverMap", serverMap) 
             , ("serverPlayers", show serverPlayers) 
             , ("serverMaxPlayers", show serverMaxPlayers) ] 

は(私はText.JSONパッケージを使用しています):今のところ、私はそのようなことを、断片的ヘルパー関数jsonifyを書きました。これは明らかに理想的ではありません。しかし、この段階では、インスタンスを使用してレコードのシリアライザを定義することは理解できません。そのための試みはタイプシステムの不満の壁になりました。

誰かがこれを行う「正しい」方法で私を歩いてもらえますか?レコードをシリアライズするinstanceを定義するにはどうすればよいでしょうか? instance(showJSON?)で使用する関数は何ですか?

ご協力いただきありがとうございます。

答えて

6

あなたはText.JSONの後継とみなされるかもしれない代わりにData.Aesonを使用して検討する必要があります。

aesonとすると、シリアライズ/デシリアライズ用に別々のインスタンスを定義します(Text.JSONが1つだけ必要な場合でも両方向を定義する必要があります。そうしないと、何らかの理由で警告が消えない限りコンパイルできません)。インスタンスをよりコンパクトにするオペレータはほとんどありません。 aeson APIで以下のように@のHAMMARの答えからの例では、少しノイズの少ない書くことができます。

instance ToJSON SRCDS.GameServerInfo where 
    toJSON (SRCDS.GameServerInfo {..}) = object 
     [ "serverName"  .= serverName 
     , "serverMap"  .= serverMap 
     , "serverPlayers" .= serverPlayers 
     , "serverMaxPlayers" .= serverMaxPlayers 
     ] 
+0

ありがとうございます。私はData.Aesonが言及したのを見ましたが、Text.JSONはまだ正式な実装であるように見えました。私は今夜​​Data.Aesonパッケージを試してみましょう。それは非常にきれいに見える:)。 – frio

+0

@frio、 'Text。JSONは実際には長い間 "正式な実装"でしたが、現在はData.Aesonにシフトが発生しています... – hvr

1

簡単なことは、record wildcardsを使用してパターンコードを減らすことです。

タイプシステムの問題については、エラーメッセージやこれまでに試したことがないと助けを与えるのは難しいですが、混乱するかもしれない1つのことは、toJSObjectの結果をラップする必要があることです戻り値の型がshowJSONJSObjectデータコンストラクタはJSValueとします。同様に、オブジェクトの値もJSValueである必要があります。これを行う最も簡単な方法は、JSONインスタンスを使用し、値を変換するためにshowJSONを呼び出すことです。

instance JSON SRCDS.GameServerInfo where 
    showJSON (SRCDS.GameServerInfo {..}) = 
     JSObject $ toJSObject [ ("serverName", showJSON serverName) 
           , ("serverMap", showJSON serverMap) 
           , ("serverPlayers", showJSON serverPlayers) 
           , ("serverMaxPlayers", showJSON serverMaxPlayers) ] 
+0

興味深い、ワイルドカードを記録するポインタのためのおかげで - 確かに私は定型的に削減に役立つだろう! すぐにコードを試しますが、JSObjectの出力をtoJSObject出力にラップすることは、(多くの、かなりランダムな)問題の1つを解決するように見えます。 'showJSON'インスタンスの' toJSObject'をレコードのシリアル化の優先/標準的な方法と呼んでいますか? – frio

+0

@frio:あなたの型を 'JSValue'に変換するスキームは' readJSON'が書式と一致していれば問題ありません。 'toJSObject'はレコードタイプに適しているようです。 – hammar

+0

素晴らしい、よかった。 – frio

関連する問題