【发布时间】:2018-03-09 07:57:10
【问题描述】:
我目前正在为 golang 中的博客开发 JSON API,但在尝试处理博客文章的序列化和反序列化时遇到了障碍。我希望我的帖子包含一系列帖子部分,这些部分可能是很多东西(例如普通段落、图像、引用等)。我正在使用 Mongo 进行存储(带有惊人的 mgo library),我想保存这样的帖子:
{
"title": "Blog post",
"sections": [
{
"type": "text",
"content": { "en": "English content", "de": "Deutscher Inhalt" }
},
{
"type": "image",
"content": "https://dummyimage.com/100x100"
},
...more sections
],
...other fields
}
我已经尝试了几种解决方案来实现这一点,但没有一个看起来是真正的“正确方法”:
- 不关心内容
这似乎是显而易见的解决方案,只需使用一个简单的结构:
type PostSection struct{
Type string
Content interface{}
}
这样,我可以通过任何前端 POSTS 并保存它。但是,操作数据或验证数据变得不可能,所以这不是一个好的解决方案。
- 使用自定义接口序列化
我发现this article 关于在 golang 中序列化接口。起初这看起来很棒,因为我可以有这样的界面:
type PostSection interface{
Type() string
Content() interface{}
}
然后像这样实现每个类型:
type PostImage string
func (p *PostImage) Type() string {
return "image"
}
func (p *PostImage) Content() interface{} {
return p
}
最好是这样,在为我的所有类型实现 MarshalJSON 和 UnmarshalJSON 之后,直接在 PostSection 对象上使用 json.Marshal 时它工作正常。
但是,当序列化或反序列化包含PostSections 数组的整个 Post 对象时,我的自定义代码将被忽略,而 PostSections 将被视为底层对象(string 或 map[string]string 在示例)在序列化时,或在反序列化时导致空对象。
- 为整个 Post 结构编写自定义序列化
因此,我目前正在使用但想要更改的解决方案是对整个 Post 对象进行自定义序列化。这会导致代码超级丑陋,因为我只需要为单个字段自定义代码,所以我将通过其余部分,使反序列化看起来类似于:
p.ID = decoded.ID
p.Author = decoded.Author
p.Title = decoded.Title
p.Intro = decoded.Intro
p.Slug = decoded.Slug
p.TitleImage = decoded.TitleImage
p.Images = decoded.Images
...more fields...
然后,像这样解码这些部分:
sections := make([]PostSection, len(decoded.Sections))
for i, s := range decoded.Sections {
if s["type"] == "text" {
content := s["content"].(map[string]interface{})
langs := make(PostText, len(content))
for lang, langContent := range content {
langString := langContent.(string)
langs[lang] = langString
}
sections[i] = &langs
} else if s["type"] == "image" {
content := s["content"].(string)
contentString := PostImage(content)
sections[i] = &contentString
}
}
p.Sections = sections
每次我想在其他地方(例如在时事通讯中)以另一种形式包含 PostSection 时,我都必须使用大量代码,而且从长远来看,它不像是惯用的 go 代码。此外,格式错误的部分没有错误处理 - 它们只会导致这样的恐慌。
这个问题有干净的解决方案吗?
【问题讨论】:
-
#2,
when serializing or deserializing an entire Post object containing an array of PostSections, my custom code was not being used and I would get errors。什么错误?您是否为 Post 对象本身实现了MarshalJSON和UnmarshalJSON? -
对不起,我好像记错了。我只是再次尝试,并且仅在尝试从 mgo 反序列化时出现错误,因为它找不到 PostSection 接口的
SetBSON方法。至于你的第二个问题,我在#3 中谈到。
标签: json go serialization