Haskell Aeson 如何基于 `Value` 类型而不是 `ByteString` 进行解码/解析?

标签 haskell aeson

我有以下功能:

parseUserBasic :: ByteString -> Either String [Either String UserBasic]
parseUserBasic x = do 
  xx <- parseItems x
  pure $ fmap (eitherDecode . encode) (items xx)

但是它不是很有效,因为 pure $ fmap (eitherDecode . encode) (items xx) - 我们将 Object JSON 编码为 ByteString,然后我们将其解码为 UserBasic。有没有办法直接做到这一点?我假设此函数的类型为 FromJSON a => Value -> Maybe a

完整代码:

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}

module UserBasic where

import GHC.Generics
import Data.Aeson
import Data.String.Conversions
import Data.ByteString.Lazy

data UserBasic = UserBasic
  { email :: String
  , name :: String
  , address_1 :: Maybe String
  , address_2 :: Maybe String
  , address_3 :: Maybe String
  , address_4 :: Maybe String
  } deriving (Generic, Show)

data Items = Items
  { items :: [Object]
  } deriving (Generic, Show)

instance FromJSON Items where
instance ToJSON Items where
  toEncoding = genericToEncoding defaultOptions

instance FromJSON UserBasic where
     parseJSON = withObject "Person" $ \v -> UserBasic
         <$> v .: "email"
         <*> ((++) . (++ " ") <$> v .: "first_name" <*> v .: "last_name")
         <*> v .: "first_name"
         <*> v .: "first_name"
         <*> v .: "first_name"
         <*> v .: "first_name"

parseItems :: ByteString -> Either String Items
parseItems = eitherDecode

parseUserBasic :: ByteString -> Either String [Either String UserBasic]
parseUserBasic x = do 
  xx <- parseItems x
  pure $ fmap (eitherDecode . encode) (items xx)

最佳答案

我推荐以下缩写代码:

newtype Items = Items
  { items :: [UserBasic]
  } deriving (Generic, Show)

instance FromJSON Items
instance ToJSON Items where
  toEncoding = genericToEncoding defaultOptions

parseUserBasic :: ByteString -> Either String [UserBasic]
parseUserBasic bs = items <$> eitherDecode bs

-- OR, even better in many cases, don't bother unwrapping Items:

parseItems :: ByteString -> Either String Items
parseItems = eitherDecode -- why even bother naming parseItems lmao

不要先解码为Object,再解码;只需直接解码为您关心的类型即可。

关于Haskell Aeson 如何基于 `Value` 类型而不是 `ByteString` 进行解码/解析?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63073992/

相关文章:

haskell - 将 Store comonad 箭头化

json - 使用 Aeson 解码字符串时遇到问题

haskell - Haskell 中的刚性类型变量错误

scala - 一步一步/深入解释 : The Power of (Co)Yoneda (preferably in scala) through Coroutines

haskell - 用 aeson 解析 utctime

haskell - 不同eDSL之间的转换(不同类型类别约束)

json - Aeson 使用的默认 ToJson 格式规范

haskell - 让 Aeson 处理混合类型的列表

json - Haskell, Aeson - 是否有更好的解析历史数据的方法?

haskell - 将新字段添加到带有 "lens"的 JSON 对象