Extract the Text from a JSON value String Text without pattern matching

点点圈 提交于 2019-12-13 19:17:54

问题


Here is the definition for a 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

I'm looking a function like where I could get the Text from String without to do some pattern matching, obviously this function will be unsafe... a fromString like fromJust in Data.Maybe for example... Something in Data.Lens.Aeson ?


回答1:


As Thomas M. DuBuisson implies in the above comment, this sounds like an XY Problem. Still, I'll do my best to nonetheless address the specifics.

Technically, you can trivially write a function with the type Value -> Text, although it requires pattern matching. I realise that the OP requests a function without pattern matching, but please read on:

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

Such a function compiles, but is unsafe!

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

While it works for String values, it crashes for any other type of value. While it's technically possible to write and compile unsafe functions like the above, AFAICT it's not considered idiomatic Haskell.

A better alternative is a safe function that returns Maybe Text. This is still easy to write using pattern matching:

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

This function is total:

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

If you don't wish to write such a function yourself, but prefer to use lens-aeson, you can use the _String prism:

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

As you can tell, this is also safe, in that ^? _String returns 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

If you really, really want an unsafe function, you can use ^?! _String:

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

It is, not surprisingly, unsafe:

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

I wonder why you're asking about this sort of functionality, though. Is there a specific problem you're trying to solve with Aeson that we can help with?



来源:https://stackoverflow.com/questions/53961314/extract-the-text-from-a-json-value-string-text-without-pattern-matching

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!