我目前正在为golang中的博客开发JSON API,并且遇到了处理博客文章的序列化和反序列化的障碍。我希望我的帖子包含一系??列帖子部分,这些帖子部分可以是很多东西(例如普通段落,图像,引号等)。我正在使用Mongo进行存储(带有令人惊叹的mgo库),并且我想保存这样的帖子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | { "title":"Blog post", "sections": [ { "type":"text", "content": {"en":"English content","de":"Deutscher Inhalt" } }, { "type":"image", "content":"https://dummyimage.com/100x100" }, ...more sections ], ...other fields } |
我已经尝试了几种解决方案来实现此目标,但似乎没有一种真正的"正确方法":
这似乎是显而易见的解决方案,仅使用简单的结构即可:
1 2 3 4 | type PostSection struct{ Type string Content interface{} } |
这样,我可以遍历任何前端POSTS并保存它。但是,操作或验证数据变得不可能,因此这不是一个好的解决方案。
我发现这篇关于在golang中序列化接口的文章。一开始这看起来很棒,因为我可以有一个像这样的界面:
1 2 3 4 | type PostSection interface{ Type() string Content() interface{} } |
然后实现这样的每种类型:
1 2 3 4 5 6 7 8 9 | type PostImage string func (p *PostImage) Type() string { return"image" } func (p *PostImage) Content() interface{} { return p } |
理想的情况就是这样,在为所有类型实现
但是,当序列化或反序列化包含
因此,我当前正在使用但想更改的解决方案是针对整个Post对象的自定义序列化。这会导致代码过于丑陋,因为我只需要单个字段的自定义代码,因此我将遍历其余部分,从而使反序列化看起来与此类似:
1 2 3 4 5 6 7 8 | 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... |
然后,像这样解码这些部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 |
每当我想在其他地方以其他形式(例如在时事通讯中)以其他形式包含PostSections时,都必须使用大量的代码,而且从长远来看,它并不像惯用的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中讨论。
为了避免为整个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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 } |