5 ms·
All of the examples of aeson I've seen have been for very simple, flat, json objects. What happens when you have json with nested objects. Do you have to create
by MatthewPhillips 13y ago
All of the examples of aeson I've seen have been for very simple, flat, json objects. What happens when you have json with nested objects. Do you have to create types for each intermediate json object or can you pull the values out into the top level type? If so how?
- jb55 13y agoAs long as your nested types have implemented or derived the ToJSON typeclass, nested structures will serialize just fine
- nightski 13y agoNested json objects are no different. You do not need to create an intermediate data type for each json object (that would be ridiculous). The docs are pretty clear on this, a quick hoogle of hackage would get you what you need.
- ocharles 13y agoWhen it comes to encoding JSON, you don't have to represent everything. For example, you can always do: object [ "foo" .= object [ "bar" .= [ "Yum", "Waffles!"] ] ] Which will give you {"foo": {"bar": ["Yum", "Waffles!"]}}. You can do traversals when decoding too: tasty :: JSON -> Parser [String] tasty json = json .: "foo" >>= (.: "bar") You can also do similar things with lens-aeson: tasty json = json & key "foo" . key "bar" . _Array Though I'm less familiar with that, and you won't be inside the Parser monad.
- awj 13y agoAeson is built on the Show and Generic type classes. Anything that supports those also basically supports the FromJSON/ToJSON classes that Aeson needs. Lists already support it (for types that also support aeson), as do Map/HashMap for various text types mapping to something that supports aeson. So, complex nested structures are a matter of defining Show and Generic instances for any types that don't already have them. From there you can trivially make those types aeson-compatible. Since so many common types are already supported, adding support for your own nested types isn't too difficult. The example use automatic derivation of Generic instances, which may result in some performance problems but is the easiest way to get off the ground.
- mxavier 13y agoWhen I code in Haskell, the first and most important step I make is to create rich types for the domain I'm working in. If you disambiguate your types, your code becomes more readable and the compiler is a lot better able to help you out when you make a mistake. For example, rather than having an Invoice with a status field of Text or String, I have a type InvoiceStatus = Paid | Unpaid | Void. From there, you can write a very precise parser that takes exactly what you want and nothing else. When I apply this approach to each component of the thing I need to parse (or do it generically even), I don't really find myself having to munge javascript types into my data structures.
- awj 13y agoTo expand on that, these "custom" types are really the only time you have to do any extra work for support with aeson. If you leave your status field as Text or String it's implicitly supported. That said, aeson support for nullary types (i.e. types that hold no "extra" values, like InvoiceStatus above) is trivial and the types make a huge difference in the rest of your code.