deriveJSON for Either a b #188

Closed
itchyny opened this Issue Mar 8, 2014 · 4 comments

Projects

None yet

3 participants

@itchyny
itchyny commented Mar 8, 2014

I'm new to this library and I found that deriveJSON is very powerful.

I noticed that Maybe a in a data field works as expected.

{-# LANGUAGE TemplateHaskell, OverloadedStrings #-}
import Data.Aeson
import Data.Aeson.TH

data D = D { number :: Maybe Int }
        deriving (Eq, Show)

$(deriveJSON defaultOptions ''D)

main :: IO ()
main = do
  print (decode "{}" :: Maybe D)
  print (decode "{\"number\": 10}" :: Maybe D)

The result is

Just (D {number = Nothing})
Just (D {number = Just 10})

However, I could not use Either.

{-# LANGUAGE TemplateHaskell, OverloadedStrings #-}
import Data.Aeson
import Data.Aeson.TH

data D = D { number :: Either Int String }
        deriving (Eq, Show)

$(deriveJSON defaultOptions ''D)

main :: IO ()
main = do
  print (decode "{\"number\": 10}" :: Maybe D)
  print (decode "{\"number\": \"30\" }" :: Maybe D)

The result is

Nothing
Nothing

If the result was like the following, it would be nice.

Just (D {number = Left 10})
Just (D {number = Right "30"})

Moreover, it would be nice if we can use deriveJSON for a data like the following.

data D = D { number :: Maybe (Either Int String) }
@basvandijk basvandijk was assigned by bos Jul 5, 2014
@itchyny
itchyny commented Dec 14, 2014

This feature will not be implemented in the future? :(

@itchyny itchyny closed this Jan 4, 2015
@mgsloan
mgsloan commented Jan 5, 2015

Yup, this should indeed be closed. There are a couple good reasons not to implement this:

  1. What do you do about Either Int Int?

  2. This would change the encoding of Either, which would break data compatibility between aeson versions.

@itchyny
itchyny commented Jan 5, 2015

Reasoning as follows. Consider a simple configuration syntax accepting a dictionary. What if I want to accept both a number and an array of numbers with the same key?

position: 10
position:
  - 10
  - 20
  - 30

We cannot implement this with deriveJSON unfortunately.

@mgsloan
mgsloan commented Jan 5, 2015

Sure, but that can easily be implemented by writing ToJSON / FromJSON instances - not everything needs to be derive-able. Since Either has an existing serialization which can handle Either a a, this is certainly a better default.

You could add your own datatype for such functionality, but note there will be no way to enforce that the encodings of the two datatypes will allow distinction between Left and Right. Even if Haskell had type inequality, it wouldn't be possible to know that the encodings of the two types don't use indistinguishable JSON.

One thought I had is that you could add some instances for http://hackage.haskell.org/package/these-0.4.2/docs/Data-These.html . Then, if the input parses as both the a type and the b type, you get both! This makes serialization problematic, though - given a These value, which serialization do you prefer?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment