在Haskell中使用JSON来序列化记录

时间:2011-07-24 00:12:32

标签: json haskell

我一直致力于一个非常小的程序来获取有关Half Life 2服务器的详细信息(使用protocol-srcds库)。工作流程非常简单;它从文件中获取服务器列表,查询每个服务器,并将输出写入另一个文件(由PHP脚本读取以供显示,因为我与vBulletin绑定)。如果它是在SQL或其他东西中完成的话会很好,但看到我还在学习,现在这已经太过分了!

无论如何,我的问题与序列化有关,即序列化为JSON。现在,我写了一个有争议的帮助函数jsonify,这样:

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包)。这显然不太理想。但是,在这个阶段,我不明白使用实例为记录定义序列化程序,而我这样做的尝试在类型系统中遇到了挫败感。

有人可以通过“正确”的方式告诉我这样做吗?我如何定义序列化记录的instance?我应该在instance(showJSON?)中使用哪些函数。

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:6)

您可能需要考虑使用Data.Aeson代替可能被视为Text.JSON的继承者。

使用aeson为序列化/反序列化定义单独的实例(使用Text.JSON即使只需要一个,也必须定义两个方向,否则编译会惹恼你 - 除非你让警告静音不知何故),它提供了一些运算符使定义实例更紧凑,例如来自@ hammar的答案的例子可以写得稍微吵一点,如下面的aeson API所示:

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

答案 1 :(得分:1)

您可以做的一件简单事情就是使用record wildcards来减少模式代码。

至于你的类型系统问题,很难在没有看到错误消息的情况下提供帮助以及你到目前为止所尝试的内容,但我怀疑有一件事可能令人困惑的是toJSObject的结果将不得不被包装在JSObject数据构造函数中,因为showJSON的返回类型应该是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) ]