-- | helper to dive into object hierarchies
-- I thought withObject would do this (one level), but found out it does not.
-- The Value is verified to be an Object, then the named fields from
-- it are selected in order, all expected to be nested object. The extractA
-- function is applied to the innermost object to yield the desired result a.
inPath :: [Text] -> (Object -> Parser a) -> Value -> Parser a
inPath fs extractA = withObject ("path " ++ T.unpack (T.intercalate "." fs))
                                (foldr descend extractA fs)
  where descend :: Text -> (Object -> Parser a) -> Object -> Parser a
        descend n f o = o .: n >>= withObject (T.unpack $ T.unwords ["object",n]) f
        -- meaning: "parse an object called n inside o, then do f with it"
{-
with an Object -> Parser a function:

   (Object -> Parser a) -> Text -> (Object -> Parser a)
   \ extractO              name ->
         withObject (printf "object with %s" name)
                    (\o -> o .: name >>= extract)

-}

-- | The JSON parser for DRResponse a uses a parseJSONPayload parser for a.
inPath :: [Text] -> (Object -> Parser a) -> Value -> Parser a
inPath fs extractA = withObject ("path " ++ T.unpack (T.intercalate "." fs))
                                (foldr descend extractA fs)
  where descend :: Text -> (Object -> Parser a) -> Object -> Parser a
        descend n f o = o .: n >>= withObject (T.unpack $ T.unwords ["object",n]) f
        -- meaning: "parse an object called n inside o, then do f with it"
{-
with an Object -> Parser a function:

   (Object -> Parser a) -> Text -> (Object -> Parser a)
   \ extractO              name ->
         withObject (printf "object with %s" name)
                    (\o -> o .: name >>= extract)

-}

-- | The JSON parser for DRResponse a uses a parseJSONPayload parser for a.
inPath fs extractA = withObject ("path " ++ T.unpack (T.intercalate "." fs))
                                (foldr descend extractA fs)
  where descend :: Text -> (Object -> Parser a) -> Object -> Parser a
        descend n f o = o .: n >>= withObject (T.unpack $ T.unwords ["object",n]) f
        -- meaning: "parse an object called n inside o, then do f with it"
{-
with an Object -> Parser a function:

   (Object -> Parser a) -> Text -> (Object -> Parser a)
   \ extractO              name ->
         withObject (printf "object with %s" name)
                    (\o -> o .: name >>= extract)

-}

-- | The JSON parser for DRResponse a uses a parseJSONPayload parser for a.