使用Aeson将嵌套的JSON解析为Tuples列表。

问题描述 投票:0回答:1

假设我有以下结构。

data AddressDto = AddressDto
  { addressDtoId                   :: UUID 
  , addressDtoCode                 :: Text
  , addressDtoCity                 :: Maybe Text 
  , addressDtoStreet               :: Text 
  , addressDtoPostCode             :: Text
  } deriving (Eq, Show, Generic)

instance FromJSON AddressDto where
  parseJSON = genericParseJSON $ apiOptions "addressDto"

instance ToJSON AddressDto where
  toJSON = genericToJSON $ apiOptions "addressDto"
  toEncoding = genericToEncoding $ apiOptions "addressDto"

这就像你所期望的那样

现在说我想解析一个格式为JSON的结构。

{ UUID: AddressDto, UUID: AddressDto, UUID: AddressDto }

一个合理的Haskell表达方式似乎是:

data AddressListDto = AddressListDto [(UUID, AddressDto)]

创建一个像这样的辅助函数

keyAndValueToList :: Either ServiceError AddressListDto -> Text -> DiscountDto -> Either ServiceError AddressListDto
keyAndValueToList (Left err) _ _ = Left err
keyAndValueToList (Right (AddressListDto ald)) k v = do
  let maybeUUID = fromString $ toS k 
  case maybeUUID of 
    Nothing        -> Left $ ParseError $ InvalidDiscountId k
    Just validUUID -> Right $ AddressListDto $ (validUUID, v) : ald

最后再创建一个FromJSON的实例

instance FromJSON AddressListDto where
  parseJSON = withObject "tuple" $ \o -> do 
    let result = foldlWithKey' keyAndValueToList (Right $ AddressListDto []) o
    case result of
      Right res -> pure res
      Left err -> throwError err

这样就不能编译了

Couldn't match type ‘aeson-1.4.5.0:Data.Aeson.Types.Internal.Value’
                     with ‘AddressDto’
      Expected type: unordered-containers-0.2.10.0:Data.HashMap.Base.HashMap
                       Text AddressDto

有两个问题:

1) 我如何确保Hashmap中的嵌套值被正确地解析为AddressDto.2) 我如何避免将初始值强行转化为一个要么?我是否可以使用一个函数来代替 foldlWithKey' 那没有让我把初始值包成这样?

json parsing haskell aeson
1个回答
1
投票

有趣的答案。要实现 parseJSON,您可以使用

parseJSON :: Value -> Parser (HashMap Text AddressDto)

...但更好的是,为什么不直接使用类型别名而不是一个新的数据类型,所以。

type AddressListDto = HashMap UUID AddressDto

这个类型已经有一个合适的 FromJSON 实例,那么你甚至不需要自己写任何代码。

© www.soinside.com 2019 - 2024. All rights reserved.