1. Untyped mode. Here we parse out values of type, amusingly, Value which reflect the total, untyped structure of JSON. We can then express queries deep inside of that structure and see what get's pulled out. For instance, using the `lens-aeson` package
v :: Value
x :: Maybe Integer -- Maybe means it might fail
x = v ^? key "foo"
. key "bar"
. key "baz"
. ix 3
. _Integer -- looks a bit like XPath, right?
2. Typed mode. Now we suggest to Aeson that some of the types of our program have direct translation into or from JSON (or both) and let the parser produce these translations in a type safe way. For instance, should we have a type like data Point = Point { x :: Double, y :: Double }
then we can introduce a translation like instance FromJSON Point where
parseJSON = withObject "Point" $ \o ->
Point <$> o .: "x"
<*> o .: "y"
which indicates that JSON objects of a syntax like `{"x": 1, "y": 1}` can be parsed into `Point`s. Technically, the parser designed there is minimal in that JSON objects with more fields can still be properly parsed, although that can be fixed.Finally, you can easily anoint your untyped mode XPath-like queries with typed fragments. This is especially powerful if your typed fragments include untyped JSON Value fragments inside of them. It means that we can use lenses to dive into an untyped JSON Value, parse some fragment of it into a Point in a type-sensitive fashion, then dive further into that Point. If Points contained more JSON values then that "further dive" could be untyped or typed again.