Reputation: 2710
I have been toying around with the JSON module for Haskell, and I wanted to manually create some JSON, close to this:
{
"data": { "unit": "cm" },
"name": "Hodor"
}
So I tried something like this:
toJSObject [
("data", toJSObject [ ("unit", toJSString "cm") ]),
("name", toJSString "Hodor")
]
However, I kept getting type mismatches because the data
field is of type JSObject JSString
, while the name
field is of type JSString
. Why is it not able to infer the general type JSValue
-- both JSObject
and JSString
should be a subtype. What am I missing?
Thanks in advance!
Upvotes: 3
Views: 357
Reputation: 8409
As J. Abrahamson pointed out there is no subtype polymorphism in Haskell so you can't represent a list of distinct types. The JSON Value
sum type provided by Aeson library ( the de-facto JSON library) can be used for constructing a JSON "heterogeneous" JSON where all values are wrapped up the uniform Value
type.
type Object = HashMap Text Value
type Array = Vector Value
-- | A JSON value represented as a Haskell value.
data Value = Object !Object
| Array !Array
| String !Text
| Number !Scientific
| Bool !Bool
| Null
Using this we create a type M.HashMap Text Value
and wrap it in an Object.
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import qualified Data.HashMap.Strict as M
example :: Value
example = Object $ M.fromList [
("data", Object $ M.fromList [ ("unit", "cm") ]),
("name", "Hodor")
]
main = print $ encode example
Which gives you the lazy bytestring: {"data":{"unit":"cm"},"name":"Hodor"}
Upvotes: 4