使用Aeson泛型来构造一个以值作为键来保存另一个值的JSON [英] Using Aeson generics to construct JSON with a value as key holding another value

查看:74
本文介绍了使用Aeson泛型来构造一个以值作为键来保存另一个值的JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试使用Aeson JSON库时,使用github gist API进行了一些修改.我遇到了与生成的ToJSON实例有关的问题,我不知道确切如何解决它.

Toying a bit with the github gist API while trying to get down with the Aeson JSON library. I've run into a problem with the generated ToJSON instance, and I don't know exactly how to solve it.

我需要在其中包含一个值,并且与该值关联的键也必须是一个值,而不是预定义的键名.显示起来有点容易.所需的输出是

I need to contain a value inside and the key that is associated to the value also needs to be a value and not a predefined key name. It's a bit easier to show. The desired output is,

{
    "public": true, 
    "description": "Something..", 
    "files": {"This Thing.md": {"content": "Here we go!"}}
}

其中文件名的值用于保存内容,但是目前我知道了,

where the value of the filename is holding the content, but currently I get,

{
    "public": true, 
    "description": "Something..", 
    "files": {"filename": "This Thing.md", "content": "Here we go!"}
}

不是我真正需要的.当前代码是

Which isn't really what I need. The current code is,

{-# LANGUAGE OverloadedStrings, DeriveGeneric #-}
import Data.Text (Text)
import Data.Aeson
import GHC.Generics

data GistContent = GistContent
    { filename :: Text
    , content :: Text
      } deriving (Show, Generic)

instance ToJSON GistContent

data Gist = Gist
    { description :: Text
    , public      :: Bool
    , files       :: GistContent
      } deriving (Show, Generic)

instance ToJSON Gist

在可能的假设下,如何查看我的数据结构以获取所需的输出?.如果使用泛型无法实现,那么如何使用ToJSON实例(我可以?不太清楚那里的结构)吗?

Under the assumption that it is possible, how would my datastructure need to look to get the desired output?.. And if that's not possible using the generics, how'd I got about it using the ToJSON instance (I can't quite figure out the structure there either)?

推荐答案

您的问题源于不正确的架构. files当前只能包含一个GistContent,这是不必要的限制.相反,您需要一个GistContent s的列表:

Your problem stems from an incorrect schema. files can currently only contain one GistContent, which is unnecessarily limiting. Instead, you'd want to have a list of GistContents:

data Gist = Gist
    { description :: Text
    , public      :: Bool
    , files       :: [GistContent]
    } deriving (Show, Generic)

现在考虑对Gist的另一个约束:每个GistContent必须具有不同的filename.可以强制执行此操作的数据结构为 Data.HashMap.Strict.HashMap .从GistContent中取出filename并使用文件名作为键:

Now consider another constraint on Gist: each GistContent must have a different filename. A data structure that would enforce this would be Data.HashMap.Strict.HashMap. Taking the filename out of GistContent and using the filename as a key:

data GistContent = GistContent
    { content :: Text
    } deriving (Show, Generic)

data Gist = Gist
    { description :: Text
    , public      :: Bool
    , files       :: HashMap Text GistContent
    } deriving (Show, Generic)

一切顺利.

这篇关于使用Aeson泛型来构造一个以值作为键来保存另一个值的JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆