Reputation: 1359
I used the answer in json_answer (Text.JSON package) and I've got a generic json Haskell data type. It's ok to define a custom Haskell data type for certain data, but if the data I want to parse is uncertain,
For example, if I got a response A from some APIs, the field is "category" this time:
[JSObject (JSONObject {fromJSObject = [("category",JSString (JSONString {fromJSString = "photo"}))]})]
And next time, "address":
[JSObject (JSONObject {fromJSObject = [("address",JSString (JSONString {fromJSString = "http://www.example.com"}))]})]
or some other uncertain fields, and the generic json type may be nested.
how can I extract it from the json data type?
Thanks for your help.
Upvotes: 1
Views: 339
Reputation: 1359
I used Data.Aeson
library and it solved my question.
decode
in Data.Aeson
can produce a Maybe Value
result. And I used pattern matching to extract the values from the Maybe Value
result like follow:
json2Array :: Maybe Value -> Array
json2Array (Just (Array anArray)) = anArray
arrayValue2Object :: Value -> Object
arrayValue2Object (Object anObject) = anObject
And in Data.Aeson, Object
constructor is a synonym of HashMap Text Value
so I can use the
Data.HashMap.Lazy/Strict to extract the values I need.
This method may not good, but it realy helped me.
Upvotes: 2
Reputation: 483
Just looking at the documentation for Text.JSON
, something like this might work for you:
import Text.JSON
data Foo = Category String
| Address String
deriving (Show)
toJSO = JSObject . toJSObject
instance JSON Foo where
showJSON (Category s) = toJSO [("category", showJSON s)]
showJSON (Address s) = toJSO [("address", showJSON s)]
readJSON (JSObject obj) = case o of
[("category", JSString s)] -> Ok $ Category $ fromJSString s
[("address", JSString s)] -> Ok $ Address $ fromJSString s
where
o = fromJSObject obj
Basically this says: if the JSON object has just a "category" field then it's a Category, and same for "address". To really make this work you'd add another clause to the case and the readJSON for indicating a "parse" error.
Then to parse your example, you'd do:
decode "some-JSON-here" :: Result [Foo]
which magically works because of this instance:
JSON a => JSON [a]
There are probably better ways of doing this, but this worked for me and seems pretty straightforward.
Upvotes: 2