【问题标题】:Aeson: derive some (but not all) fields of a structAeson:派生结构的一些(但不是全部)字段
【发布时间】:2018-11-26 22:44:05
【问题描述】:

我有一个大型结构,我需要它是 FromJSON 的一个实例,以便我可以将我的 json 数据解析到其中。

我想自动派生,但单个字段需要“特别注意”,因为它是 json 中的一个对象,我希望它是我的结构中的值的数组。如果不编写一个巨大的 FromJson 实现来重复所有字段,我该如何做到这一点?

示例 json:

{"myobject": {"one": 1, "two": 2}, ...many_more_fields...}

示例结构:

data MyStruct = MyStruct {
  myobject :: [Int],
  ...many_more_fields,...
} deriving (Generic)

我该如何优雅地做到这一点?

【问题讨论】:

标签: json haskell aeson


【解决方案1】:

你应该为你的特殊领域创建一个newtype

newtype MySpecialType = MySpecialType [Int]

instance FromJSON MySpecialType where ....

data MyStruct = MyStruct {
      myobject:: MySpecialType,
      ...
   }

现在MyStruct 的实例变得完全正常,可以以正常方式移交给 Template Haskell。

【讨论】:

    【解决方案2】:

    为避免在整个代码库中携带来自Paul Johnson's very good answer 的新类型,您还可以将您的类型概括如下,将myobject 的类型作为参数:

    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
    

    上面的genericParseJSONMyStruct MySpecialType 实例化,然后该字段通过fmap 展开(注意MyStruct_Functor


    我也刚刚写了一个blogpost about "type surgery",适用于这种问题,这样你就可以保持原来的类型不变。

    The generic-data-surgery library 可以派生出与上述MyStruct_ MySpecialType 具有相同Generic 结构的泛型类型,供aeson 的genericParseJSON 使用。手术modifyRField 然后将函数\(MySpecialType i) -> i 应用于myobject 字段,最终产生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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-12
      • 1970-01-01
      • 1970-01-01
      • 2021-08-05
      • 2015-12-21
      • 2012-07-21
      • 2021-06-07
      • 1970-01-01
      相关资源
      最近更新 更多