Today I wanted to solve next problem.
Assume that we have typeclass DataWithDefault defined as
class DataWithDefault a where
  defaultValue :: a
And we have data Example defined as
data Example =
  Example { field1 :: Text
          , field2 :: Text
          } deriving (Show)
instance DataWithDefault Example where
  defaultValue = Example "Hello" "World"
instance FromJSON Example where
  parseJSON (Object v) =
    Example <$> v .:? "field1" .!= field1 defaultValue
            <*> v .:? "field2" .!= field2 defaultValue
  parseJSON _ = mzero
instance ToJSON Example where
 toJSON (Example f1 f2)  =
    object [ "field1" .= f1
           , "field2" .= f2
           ]
I know that Aeson uses Generics to derive FromJSON and ToJSON instances automatically, but I can't figure out how to make it derive FromJSON instance with default values for fields that are not represented in given json. Is it possible to do using generics? Actually I don't ask you a final solution, but maybe some clue? 
Update
Let me add more information about the problem.
Suppose now that you need to update your Example data and now it defined as 
data Example =
  Example { field1 :: Text
          , field2 :: Text
          , field3 :: Int
          } deriving (Show)
So you want to update DataWithDefault instance declaration
instance DataWithDefault Example where
  defaultValue = Example "Hello" "World" 12
And what I want to do is not to write
instance FromJSON Example where
  parseJSON (Object v) =
    Example <$> v .:? "field1" .!= field1 defaultValue
            <*> v .:? "field2" .!= field2 defaultValue
            <*> v .:? "field3" .!= field3 defaultValue
  parseJSON _ = mzero
And want to derive such instance definition automatically. And more importantly, I want to do it not only for Example, but for DataWithDefault a. 
Update 2
The point of combining .:? and .!= is to get as much as possible fields from given json and set every missing field to it's default value. So when we pass 
{ "field1" : "space", "field2" : "ship" }
I want my new example be not field1 = Hello; field2 = World; field3 = 12, but field1 = space; field2 = ship; field3 = 12.
Instead of making Aeson do it, just use a newtype for what they were designed for:
newtype DefaultJSON a = DefaultJSON { unDefaultJSON :: a }
instance (FromJSON a, DataWithDefault a) => FromJSON (DefaultJSON a) where
    parseJSON v = DefaultJSON <$> (parseJSON v <|> pure defaultValue)
Then you can do
> decode "{}" :: Maybe (DefaultJSON Example)
Just (DefaultJSON {unDefaultJSON = (Example {field1 = "Hello", field2 = "World"}})
This is a little different than what you asked, it provides a default value in case parsing fails, but not a default value for each field in case that individual field is missing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With