hap*_*ens 2 serialization json go
我目前正在用 golang 为博客开发 JSON API,但在尝试处理博客文章的序列化和反序列化时遇到了障碍。我希望我的帖子包含一系列帖子部分,这些部分可以是很多东西(例如普通段落、图像、引用等)。我正在使用 Mongo 进行存储(使用令人惊叹的mgo 库),我想像这样保存帖子:
{
"title": "Blog post",
"sections": [
{
"type": "text",
"content": { "en": "English content", "de": "Deutscher Inhalt" }
},
{
"type": "image",
"content": "https://dummyimage.com/100x100"
},
...more sections
],
...other fields
}
Run Code Online (Sandbox Code Playgroud)
我已经尝试了几种解决方案来在 go 中实现这一点,但没有一个真正看起来像“正确的方法”:
这似乎是显而易见的解决方案,只需使用一个简单的结构:
type PostSection struct{
Type string
Content interface{}
}
Run Code Online (Sandbox Code Playgroud)
这样,我可以通过任何前端 POSTS 并保存它。但是,操纵数据或验证数据变得不可能,因此这不是一个好的解决方案。
我找到了这篇关于在 golang 中序列化接口的文章。起初这看起来很棒,因为我可以有一个这样的界面:
type PostSection interface{
Type() string
Content() interface{}
}
Run Code Online (Sandbox Code Playgroud)
然后像这样实现每种类型:
type PostImage string
func (p *PostImage) Type() string {
return "image"
}
func (p *PostImage) Content() interface{} {
return p
}
Run Code Online (Sandbox Code Playgroud)
最理想的情况就是这样,在实现之后MarshalJSON,UnmarshalJSON对于我的所有类型,当直接在 PostSection 对象上使用 json.Marshal 时,它工作正常。
但是,在序列化或反序列化包含PostSections数组的整个 Post 对象时,我的自定义代码只是被忽略,并且 PostSections在序列化时只会被视为底层对象(string或map[string]string在示例中),或者在反序列化时导致空对象.
因此,我目前正在使用但想更改的解决方案是对整个 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...
Run Code Online (Sandbox Code Playgroud)
然后,像这样解码部分:
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
Run Code Online (Sandbox Code Playgroud)
每次我想在其他地方(例如在时事通讯中)以另一种形式包含 PostSections 时,我都必须使用大量代码,而且从长远来看,它感觉不像是惯用的 go 代码。此外,对于格式错误的部分没有错误处理 - 它们只会引起像这样的恐慌。
这个问题有干净的解决方案吗?
为了避免编写UnmarshalJSON整体,Post您可以将您PostSection的内容包装在具体类型中并让它实现 Unmarshaler 接口。
type Post struct {
ID int
Author string
Title string
Intro string
Slug string
TitleImage string
Images []string
Sections []*PostSection
}
type SectionContent interface {
Type() string
Content() interface{}
}
type PostSection struct {
Content SectionContent
}
func (s *PostSection) UnmarshalJSON(data []byte) error {
// ...
return nil
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3426 次 |
| 最近记录: |