从不带模式匹配的JSON值字符串文本中提取文本

时间:2018-12-28 16:14:29

标签: haskell lens aeson

这是Json值的定义:

-- | A JSON value represented as a Haskell value.
data Value = Object !Object
           | Array !Array
           | String !Text
           | Number !Scientific
           | Bool !Bool
           | Null
             deriving (Eq, Show)

let value = String "myValue"
looking for => fromString value == "myValue" ??
fromString :: Value -> Text

我正在寻找一个类似我可以从String获取Text而无需进行某些模式匹配的函数,显然,此函数将是不安全的... fromString类似于Data中的fromJust。例如,也许... .Lens.Aeson吗?

1 个答案:

答案 0 :(得分:1)

正如Thomas M. DuBuisson在上述评论中所暗示的那样,这听起来像XY Problem。尽管如此,我将尽力解决具体问题。

技术上,尽管它需要模式匹配,但是您可以轻松编写类型为Value -> Text的函数。我意识到OP请求的功能没有模式匹配,但请继续阅读:

-- Warning: UNSAFE!
fromString :: Value -> Text
fromString (String s) = s

这样的函数可以编译,但是不安全!

*Q53961314 Q53961314> fromString $ String "myValue"
"myValue"
*Q53961314 Q53961314> fromString $ Number 42
"*** Exception: Non-exhaustive patterns in function fromString

虽然它适用于String值,但对于任何其他类型的值都会崩溃。尽管在技术上可以像上面那样编写和编译不安全的函数,但AFAICT并不认为它是惯用的Haskell。

更好的选择是返回Maybe Text的安全函数。使用模式匹配仍然很容易写:

fromStringSafe :: Value -> Maybe Text
fromStringSafe (String s) = Just s
fromStringSafe _ = Nothing

此功能总计:

*Q53961314 Q53961314> fromStringSafe $ String "myValue"
Just "myValue"
*Q53961314 Q53961314> fromStringSafe $ Number 42
Nothing

如果您不想自己编写此类功能,而是喜欢使用lens-aeson,则可以使用_String棱镜:

Prelude Data.Aeson Data.Aeson.Lens Control.Lens> String "myValue" ^? _String
Just "myValue"

您可以说,这也是安全的,因为^? _String返回Maybe Text

Prelude Data.Aeson Data.Aeson.Lens Control.Lens> Bool True ^? _String
Nothing
Prelude Data.Aeson Data.Aeson.Lens Control.Lens> Number 42 ^? _String
Nothing

如果您确实要使用不安全的功能,则可以使用^?! _String

Prelude Data.Aeson Data.Aeson.Lens Control.Lens> String "myValue" ^?! _String
"myValue"

这并不奇怪,不安全:

Prelude Data.Aeson Data.Aeson.Lens Control.Lens> Number 42 ^?! _String
"*** Exception: (^?!): empty Fold
CallStack (from HasCallStack):
  error, called at src\\Control\\Lens\\Fold.hs:1285:28 in lens-4.17-7m3etWEBj0P3172qv7LEG9:Control.Lens.Fold
  ^?!, called at <interactive>:9:1 in interactive:Ghci3

我想知道为什么您要问这种功能。您要使用Aeson解决的特定问题是否可以解决?