首页 > 解决方案 > 从没有模式匹配的 JSON 值字符串文本中提取文本

问题描述

这是 Json Value 的定义:

-- | 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

我正在寻找一个函数,比如我可以从字符串中获取文本而无需进行一些模式匹配,显然这个函数将是不安全的……一个 fromString 就像 Data.Maybe 中的 fromJust 一样……Data.Lens 中的一些东西。埃森?

标签: haskellhaskell-lensaeson

解决方案


正如 Thomas M. DuBuisson 在上述评论中暗示的那样,这听起来像是一个XY Problem。尽管如此,我还是会尽力解决细节问题。

从技术上讲,您可以轻松地编写一个带有 type 的函数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 解决我们可以帮助解决的具体问题?


推荐阅读