2012-01-15 3 views
1

Я создаю API-интерфейс JSON REST (там много колпачков), и у меня уже есть Data.Aeson.Generic. В дальнейшем, serializedString будет {"x":10, "y":10}Haskell JSON Rest API - как обобщить метаинформацию?

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) 

Я хотел бы, чтобы мой апи ответить, как это за успехи:

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

И это за неудачи

{error:"Didn't work!"} 

Я думал что делает тип данных Response, с Response и Error конструкторами. Легко сериализовать Error, но ответ может иметь все виды разных объектов, а не отправлять обратно {data:{...}} Я бы хотел сделать {unit:{...}}.

Есть ли способ определить мой конструктор значений Response так, чтобы он работал с чем-либо, производящим Data? Есть ли способ узнать, что такое имя конструктора значений, когда я перехожу к сериализации моего объекта? show знает это как-то. Благодаря!

ответ

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 на сообщение верхнего уровня. Ключевой концепцией, которую я отсутствовал, был typeOf из Data.Data.Typeable. Он дает вам строку, представляющую конструктор данных. Это будет интересно попробовать пойти в другом направлении, используя FromJSON

Edit: быть ясно, то вы можете позвонить и получить Data.Aeson.encode $ Message $ Unit 10 10{unit:{x:10, y:10}}

Смежные вопросы