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:
data MyStruct_ intList = MyStruct {
myobject :: intlist,
...
} deriving (Functor, Generic)
type MyStruct = MyStruct [Int]
instance FromJSON MyStruct where
parseJSON = (fmap . fmap) (\(MySpecialType i) -> i)
. genericParseJSON defaultOptions
genericParseJSON
above gets instantiated with MyStruct MySpecialType
, and then the field gets unwrapped via fmap
(noting MyStruct_
is a Functor
)
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 as MyStruct_ MySpecialType
above, to be used by aeson's genericParseJSON
. The surgery modifyRField
then applies the function \(MySpecialType i) -> i
to the myobject
field, finally yielding MyStruct
.
import Generic.Data.Surgery (fromOR, toOR', modifyRField)
-- The original type
data MyStruct = MyStruct {
myobject :: [Int],
...
} deriving (Generic)
instance FromJSON MyStruct where
parseJSON = fmap (fromOR . modifyRField @"myobject" (\(MySpecialType i) -> i) . toOR')
. genericParseJSON defaultOptions