Aeson: derive some (but not all) fields of a struct
我有一个大型结构,我需要它是 FromJSON 的一个实例,以便我可以将我的 json 数据解析到其中。
我想自动派生,但是单个字段需要”特别注意”,因为它是 json 中的一个对象,我希望它是我的结构中的值的数组。在不编写重复所有字段的巨大 FromJson 实现的情况下如何做到这一点?
示例 json:
1
|
{“myobject”: {“one”: 1,“two”: 2}, …many_more_fields…}
|
示例结构:
1
2 3 4 |
我该如何优雅地做到这一点?
- 相关:stackoverflow.com/questions/53352563/
你应该为你的特殊领域创建一个 newtype:
1
2 3 4 5 6 7 8 |
newtype MySpecialType = MySpecialType [Int]
instance FromJSON MySpecialType where …. data MyStruct = MyStruct { |
现在 MyStruct 的实例变得完全正常并且可以以正常方式移交给 Template Haskell。
为了避免在整个代码库中使用 Paul Johnson 非常好的答案中的 newtype,您还可以将您的类型概括如下,将 myobject 的类型作为参数:
1
2 3 4 5 6 7 8 9 10 |
上面的
genericParseJSON 用 MyStruct MySpecialType 实例化,然后该字段通过 fmap 展开(注意 MyStruct_ 是 Functor)
我也刚刚写了一篇关于”类型手术”的博文,适用于这种问题,这样你就可以保持原来的类型不被修改。
generic-data-surgery 库可以派生出与上述MyStruct_ MySpecialType具有相同Generic结构的泛型类型,供aeson的genericParseJSON使用。手术 modifyRField 然后将函数 \\(MySpecialType i) -> i 应用于 myobject 字段,最终产生 MyStruct.
1
2 3 4 5 6 7 8 9 10 11 |
import Generic.Data.Surgery (fromOR, toOR’, modifyRField)
— The original type instance FromJSON MyStruct where |
来源:https://www.codenong.com/53448958/