-
Notifications
You must be signed in to change notification settings - Fork 323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Split generic deriving into specific cases, powered by DerivingVia. #933
Comments
Sounds good! Does DerivingVia compose well? E.g. if I want to use both |
It doesn't. Each "newtype" has to implement the features, but can use the same auxiliary code for that. |
That approach tends to lead to orphan instances. Are those considered okay here? |
@treeowl they won't be orphans, as in my plan there are no default definitions. |
But there need to be instances, right? And presumably the newtype representing the current default will be used for some of them? |
It isn't currently, I don't see why situation would dramatically change. |
Oh, didn't realize they weren't used for |
2.0.3.0 added instance for |
No, but we can have options to compose, such as in: |
Good plan @phadej, +1 ! I just had a use-case for an extended deriving strategy... but upon reading through the To sketch the idea, imagine numerous serializable record-datatypes with instances of data MyAirInfo = MyAirInfo
{ airTemperature :: Float
, airPressurePa :: !Int
, airPlanet :: Text
}
deriving Generic
deriving ToJSON via CustomJSON (KebabCaseWithoutPrefix "air") MyAirInfo
instance Default MyAirInfo where
def = MyAirInfo
{ airTemperature = 19.0
, airPressurePa = 108900
, airPlanet = "Earth"
} So, given that all fields have sane defaults, and can be omitted from input json... How to write the -- either the default values are repeated in an hand-rolled parser instance:
--
instance FromJSON MyAirInfo where
parseJSON = withObject "MyAirInfo" $ \o -> do
airTemperature <- o .:? "temperature" .!= 19.0
airPressurePa <- o .:? "pressure-pa" .!= 108900
airPlanet <- o .:? "planet" .!= "Earth"
pure MyAirInfo{..}
-- or we leverage the Default instance, but repeat field names and still hand-roll:
--
instance FromJSON MyAirInfo where
parseJSON = withObject "MyAirInfo" $ \o -> do
airTemperature <- o .:? "temperature" .!= airTemperature def
airPressurePa <- o .:? "pressure-pa" .!= airPressurePa def
airPlanet <- o .:? "planet" .!= airPlanet def
pure MyAirInfo{..}
-- instead I'd want to say:
--
deriving via CustomJSONwithDefault (KebabCaseWithoutPrefix "air") MyAirInfo instance FromJSON MyAirInfo — but
I constructively disagree. Check out the And although via-strategy newtypes can also compose by nesting — I'd suggest to not restrict any particular composition style in the core aeson library. Leave it on value-level; that's sufficient. Because 👉 fieldstrength/aeson-deriving — implements similar idea, but with a different UI (or like they say in javascript circles, "DX", developer experience). BTW, was this bug ever noticed?.. The ± infinities are flipped here. aeson/src/Data/Aeson/Types/FromJSON.hs Lines 1577 to 1582 in 98875e0
|
But specific encodings like And if the type cannot be encoded as Modifiers may be shared (e.g. how to mangle constructor names), but that's about it. Similarly, record encoding as object would have options, etc. EDIT: In particular I dislike and will remove a (default) option where |
@phadej so what about supporting generic ideas like my |
A problem I find in improving
aeson
is dealing with generic and TH code. It's monolithic, trying to cater for all needs at once.Issues like #824 and #827 is hard to incorporate as everything is coupled. Compiling generics code is also slow (#810) as simplifier needs to work out a lot of code.
I propose a long term strategy of splitting various kinds of encoding formats into separate newtype wrappers to be used with
DerivingVia
To/FromJSONObject
classes here.ToJSON
&FromJSON
modules, making working onaeson
slightly more pleasant."simplifying" generics story would also help to improve other aspects of aeson, e.g. #839 is somewhat stuck as getting the change through current generics code is very hard.
Note: TH code should be adopted to be configurable similarly to DerivingVia code, if people would prefer to use TH. This shouldn't be difficult.
In summary: 1. Add an alternative generics code to be used with
DerivingVia
. 2. Remove old generics code. 3. Profit.ping @bergmark @Lysxia
The text was updated successfully, but these errors were encountered: