on master help sign in
Change toJSON and fromJSON instances for Either.

Previously, fromJSON . toJSON == id was violated by the Either instances. In addition, if both types are parsable from the same JSON, then the Left is always given favor - which is probably not desirable. Instead, differentiate the instances using an array. This allows for "Either a a" to actually work instead of always chosing Left in FromJSON.

commit389803154c92676ae22c084ef23174170fe253d2 authorJared Hance <jaredhance@gmail.com> dateMon 25 Jul 2011, 09:46 (15 years ago) parent00a185a
1 file changed+10−3
Data/Aeson/Types.hs+10−3
Data/Aeson/Types.hs+10−3
@@ -325,12 +325,19 @@ instance (FromJSON a) => FromJSON (Maybe a) where
325325 {-# INLINE parseJSON #-}
326326
327327instance (ToJSON a, ToJSON b) => ToJSON (Either a b) where
328− toJSON (Left a) = toJSON a
329− toJSON (Right b) = toJSON b
328+ toJSON (Left a) = Array (V.fromList [String "Left", toJSON a])
329+ toJSON (Right b) = Array (V.fromList [String "Right", toJSON b])
330330 {-# INLINE toJSON #-}
331331
332332instance (FromJSON a, FromJSON b) => FromJSON (Either a b) where
333− parseJSON a = Left <$> parseJSON a <|> Right <$> parseJSON a
333+ parseJSON v@(Array vec) =
334+ if V.length vec /= 2
335+ then typeMismatch "Either a b" v
336+ else case vec V.! 0 of
337+ "Left" -> Left <$> parseJSON (vec V.! 1)
338+ "Right" -> Right <$> parseJSON (vec V.! 1)
339+ _ -> typeMismatch "Either a b" v
340+ parseJSON v = typeMismatch "Either a b" v
334341 {-# INLINE parseJSON #-}
335342
336343instance ToJSON Bool where