Haskell JSON Rest API - 如何一般地序列化元信息?

时间:2012-01-15 01:21:58

标签: json haskell

我正在创建一个JSON REST API(那里有很多大写),并且已经有了Data.Aeson.Generic正常工作。在下文中,serializedString将为{"x":10, "y":10}

import qualified Data.Aeson.Generic as A
import Data.Data (Data, Typeable)
data Unit = Unit { x :: Int, y :: Int } deriving (Show, Eq, Data, Typeable)

example = do
    let serializedByteString = A.encode (Unit 10 10)

我想让我的api像这样取得成功:

{unit:{x:10, y:10}} 

这就是失败

{error:"Didn't work!"}

我在考虑使用ResponseResponse构造函数制作某种Error数据类型。序列化Error很容易,但响应可能包含各种不同的对象,而不是发回{data:{...}}我想做{unit:{...}}

有没有办法定义我的Response值构造函数,以便它适用于派生Data的任何内容?有什么方法可以在我序列化对象时知道值构造函数的名称是什么? show以某种方式了解它。谢谢!

1 个答案:

答案 0 :(得分:1)

对于Error构造函数(我认为)不起作用,但这适用于单位

{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}

module Types where

import Data.Data (Data, Typeable, typeOf)
import Data.Aeson (ToJSON(..), (.=), object)
import qualified Data.Aeson.Generic as AG

import qualified Data.Text as T
import Data.Char (toLower)

data Unit = Unit { x :: Int, y :: Int } deriving (Show, Data, Typeable)


data Message a = Message { obj :: a } |
                 Error String 
                 deriving (Show, Data, Typeable)


instance (Data a, Typeable a) => ToJSON (Message a) where
    toJSON m = object [T.pack typeName .= AG.toJSON (obj m)]
        where o = obj m
              typeName = map toLower $ show $ typeOf o

您必须在顶级邮件上使用Data.Aeson.encode,而不是Data.Aeson.Generic.encode。我缺少的关键概念是来自Data.Data.Typeable的typeOf。它为您提供了一个表示数据构造函数的字符串。尝试使用FromJSON

进入另一个方向会很有趣

修改:要清楚,您可以拨打Data.Aeson.encode $ Message $ Unit 10 10并获取{unit:{x:10, y:10}}