12

I can't get aeson to parse an UTCTime value. I tried to encode one and feed it back, but that didn't work:

Prelude Data.Aeson Data.Time.Clock> getCurrentTime >>= (print . encode)
"\"2013-10-17T09:42:49.007Z\""
Prelude Data.Aeson Data.Time.Clock> decode "2013-10-17T09:42:49.007Z" :: Maybe UTCTime
Nothing
Prelude Data.Aeson Data.Time.Clock> decode "\"2013-10-17T09:42:49.007Z\"" :: Maybe UTCTime
Nothing

The FromJSON instance of the UTCTime type is the following (ref):

instance FromJSON UTCTime where
    parseJSON = withText "UTCTime" $ \t ->
        case parseTime defaultTimeLocale "%FT%T%QZ" (unpack t) of
          Just d -> pure d
          _      -> fail "could not parse ISO-8601 date"

following the format description found here, everything should be ok. What am I missing?

Simon Bergot
  • 10,378
  • 7
  • 39
  • 55

1 Answers1

18
Prelude Data.Aeson Data.Time> decode (encode [x]) :: Maybe [UTCTime]
Just [2013-10-17 10:06:59.542 UTC]

Note the "pitfalls" section in the haddocks:

Note that the JSON standard requires that the top-level value be either an array or an object. If you try to use decode with a result type that is not represented in JSON as an array or object, your code will typecheck, but it will always "fail" at runtime:

...

So stick to objects (e.g. maps in Haskell) or arrays (lists or vectors in Haskell):

Thomas M. DuBuisson
  • 64,245
  • 7
  • 109
  • 166
  • I had read this section. However, my brain did not make the connection. Thanks! – Simon Bergot Oct 17 '13 at 10:19
  • One practical trick for getting around this is to just wrap your types in a list layer: `decode "..." :: FromJSON a => Maybe [a]`. I use this all the time for quickchecking subparsers. It's *much* easier than trying to rewire the inner Aeson parsers to get you nonstandard JSON behavior. – J. Abrahamson Oct 17 '13 at 13:25
  • 2
    If you use the `value` parser from `Data.Aeson.Parser` you can override the spec. requirement of only parsing top-level json object / arrays, and parse individual values. Use it with attoparsec. – The Internet Dec 04 '14 at 23:25