Haskell: 带aeson的动态对象字段名

Haskell: Dynamic object field name with aeson

如果我有一个数据结构从 readFile 中获取两个值;我如何使用这些值作为我的 toJSON 实例声明的字段名?

例如在下面的代码中,名称“2015”和“2016”将根据输入文件进行更改。

data MyOutput = MyOutput
              { periodOne   :: YearInfo
              , periodTwo   :: YearInfo
              , updateStamp :: String
              } deriving (Show)

instance ToJSON MyOutput where
  toJSON MyOutput {..} =
    object [ "2015"       .= periodOne
           , "2016"       .= periodTwo
           , "Data up to" .= updateStamp
           ]

不幸的是 ToJSON 实例不能依赖于数据结构外部的值。

我的建议是更改数据结构以包含 periodOneperiodTwo 的字段名称:

data MyOutput = MyOutput {
                  periodOneName, periodTwoName :: String,
                  periodOne, periodTwo :: YearInfo
                  ...
              }

现在 toJSON 实例可以访问期间的名称。

完整示例:

{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedStrings #-}

import Data.Aeson
import qualified Data.Text as T

type YearInfo = [ Int ]

data MyOutput = MyOutput
              { periodOne   :: YearInfo
              , periodTwo   :: YearInfo
              , periodOneName :: T.Text
              , periodTwoName :: T.Text
              , updateStamp :: String
              } deriving (Show)

instance ToJSON MyOutput where
  toJSON MyOutput {..} =
    object [ periodOneName .= toJSON periodOne
           , periodTwoName .= toJSON periodTwo
           , "Data up to"  .= toJSON updateStamp
           ]