Skip to content

Decoding an encoded unary constructor fails #63

basvandijk opened this Issue Jan 14, 2012 · 1 comment

1 participant


Both Data.Aeson.Generic, Data.Aeson.TH and the GHC Generic code encode types with a single unary constructor like:

data T = C Int

using the encoding of the argument of the constructor. For example:

> toJSON (C 1)
Number 1

It can also be converted back:

> fromJSON (toJSON (C1 1)) :: Result T
Success (C1 1)

Lets try to encode it:

> encode (toJSON (C1 1))
Chunk "1" Empty

That works. Now lets try to decode this encoded value:

> decode (encode (toJSON (C1 1))) :: Maybe T

??? I would have expected to get Just (C 1).

Of course the reason this is happening is because decode only decodes a top-level JSON value which must be either an object or an array, per RFC 4627.

The question is should we change the encoding to go to a one element array instread? Bryan, what do you think?

@basvandijk basvandijk was assigned Jan 14, 2012

After thinking about this some more I think we should leave it as it is.

Because if, instead of the T type, we would have an Int the same thing would happen:

> decode (encode (toJSON 1)) :: Maybe Int

We could ask ourselves whether encode should fail on non top-level JSON values. Or maybe we could have a safeEncode function:

safeEncode :: ToJSON a => a -> Maybe ByteString
safeEncode x | topLevel v = Just $ encodeUtf8 $ toLazyText $ fromValue v
             | otherwise  = Nothing
    v = toJSON x

topLevel :: Value -> Bool
topLevel (Object _) = True
topLevel (Array  _) = True
topLevel _          = False 
@basvandijk basvandijk closed this Jan 15, 2012
@bos bos added a commit that referenced this issue Jan 21, 2012
@bos Describe fix for gh-63 in release notes f5fb0eb
@tolysz tolysz pushed a commit to tolysz/aeson that referenced this issue May 18, 2015
@bos Describe fix for gh-63 in release notes b010122
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.