Skip to content

Instantly share code, notes, and snippets.

@reite reite/gist:5568152
Last active Dec 17, 2015

Embed
What would you like to do?
parseInvoices :: L.ByteString -> Either String [Invoice]
parseInvoices s = do
result <- eitherDecode s
flip parseEither result $ \obj -> do
d <- (obj .: "invoices") >>= (.: "invoice")
case d of
Object v -> return [v]
Array v -> return v
@reite

This comment has been minimized.

Copy link
Owner Author

reite commented May 13, 2013

The structure of the json looks like this:

{"invoices":
     {"invoice": {...} or [{...}] }
}

where "invoice" will be a Array of Objects if there are more than 1 entry, or a single Object if there is only one.

@reite

This comment has been minimized.

Copy link
Owner Author

reite commented May 13, 2013

Solution:

import qualified Data.Vector as V

parseObjOrArray :: (FromJSON a) => Value -> Parser a
parseObjOrArray obj = case obj of
               ob@(Object v) -> parseJSON $ Array (V.singleton ob)
               arr@(Array v) -> parseJSON arr
               _ -> error "Expected {} or []"

Use like this:

parseInvoices :: L.ByteString -> Either String [Invoice]
parseInvoices s = do
    result <- eitherDecode s
    flip parseEither result $ \obj -> (obj .: "invoices") >>= (.: "invoice") >>= parseObjOrArray
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.