I have a large struct which I need to be an instance of FromJSON so that I can parse my json data into it.
I would like to derive automatically, but a single field needs "special care" in that it is an object in json and I want it to be an array of the values in my struct. How can I do this without writing a huge FromJson implementation repeating all the fields?
Example json:
{"myobject": {"one": 1, "two": 2}, ...many_more_fields...}
Example struct:
data MyStruct = MyStruct {
myobject :: [Int],
...many_more_fields,...
} deriving (Generic)
How do I do this elegantly?
To avoid carrying the newtype from Paul Johnson's very good answer all across the codebase, you can also generalize your type as follows, making the type of
myobject
a parameter:genericParseJSON
above gets instantiated withMyStruct MySpecialType
, and then the field gets unwrapped viafmap
(notingMyStruct_
is aFunctor
)I also just wrote a blogpost about "type surgery", applied to this kind of problem so that you can keep the original type unmodified.
The generic-data-surgery library can derive a generic type with the same
Generic
structure asMyStruct_ MySpecialType
above, to be used by aeson'sgenericParseJSON
. The surgerymodifyRField
then applies the function\(MySpecialType i) -> i
to themyobject
field, finally yieldingMyStruct
.You should create a
newtype
for your special field:Now the instance for
MyStruct
becomes entirely regular and can be handed off to Template Haskell in the normal way.