我正在创建一个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!"}
我在考虑使用Response
和Response
构造函数制作某种Error
数据类型。序列化Error
很容易,但响应可能包含各种不同的对象,而不是发回{data:{...}}
我想做{unit:{...}}
。
有没有办法定义我的Response
值构造函数,以便它适用于派生Data
的任何内容?有什么方法可以在我序列化对象时知道值构造函数的名称是什么? show
以某种方式了解它。谢谢!
答案 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}}