Автоматическое получение экземпляра для пользовательского типа данных с помощью Aeson/JSON

Если у меня есть собственный тип данных для разбора JSON с помощью Aeson

data Response = Response
    { response :: [Body]
    } deriving (Show)

instance FromJSON Response where
    parseJSON (Object v) = Response <$> v .: "response"
    parseJSON _ = mzero

data Body = Body
    { body_id               :: Int
    , brandId               :: Int
    } deriving (Show)

instance FromJSON Body where
    parseJSON (Object v) = Body
        <$> v .: "id"
        <*> v .: "brandId"
    parseJSON _ = mzero

raw :: BS.ByteString
raw = "{\"response\":[{\"id\":5977,\"brandId\":87}]}"

давая:

λ> decode raw :: Maybe Response
Just (Response {response = [Body {body_id = 5977, brandId = 87}]})

Как автоматически получить экземпляры для FromJSON?

Я пытался:

data Response = Response
    { response :: [Body]
    } deriving (Show,Generic)

data Body = Body
    { body_id               :: Int
    , brandId               :: Int
    } deriving (Show,Generic)

instance FromJSON Response
instance FromJSON Body

как было предложено в некоторых учебниках, но это дает:

λ> :l response.hs
[1 of 1] Compiling Response         ( response.hs, interpreted )

response.hs:19:22:
    Can't make a derived instance of `Generic Response':
      You need DeriveGeneric to derive an instance for this class
    In the data declaration for `Response'

response.hs:24:22:
    Can't make a derived instance of `Generic Body':
      You need DeriveGeneric to derive an instance for this class
    In the data declaration for `Body'
Failed, modules loaded: none.

Что я делаю неправильно?


person matt    schedule 29.02.2016    source источник


Ответы (1)


Ошибка говорит вам о том, что вы должны включить расширение DeriveGeneric, чтобы это работало. Итак, вы должны добавить:

{-# LANGUAGE DeriveGeneric #-}

прямо вверху вашего файла или скомпилируйте с флагом -XDeriveGeneric.

person Bakuriu    schedule 29.02.2016
comment
Спасибо! это исправило. а также спасибо за редактирование моего поста. - person matt; 29.02.2016
comment
еще кое-что. Вы заметите идентификатор в raw = "{\"response\":[{\"id\":5977,\"brandId\":87}]}" ; можно ли перезаписать часть автоматически полученного экземпляра? id явно зарезервирован, и в полученном JSON есть идентификаторы, и я бы предпочел не использовать id в моем типе данных. - person matt; 29.02.2016
comment
@matthias Я сомневаюсь, что ты сможешь это сделать. Но я не эксперт эзона. Вы можете попытаться открыть новый вопрос об этой проблеме. - person Bakuriu; 29.02.2016