Serialization Golang中的序列化模型

Serialization Golang中的序列化模型,serialization,go,Serialization,Go,我试图将我的代码划分为模型和序列化程序,其思想是有一个定义的序列化程序来处理所有json职责,即分离关注点。我还希望能够调用模型对象obj.Serialize(),以获取序列化程序结构obj,然后对其进行封送处理。因此,我提出了以下设计。为了避免循环导入,我必须在序列化程序中使用接口,这导致在模型中使用getter。我已经读到getter/setter不是惯用的go代码,我不希望所有模型都有“样板”getter代码。对于我想要完成的任务,有没有更好的解决方案,请记住我想要分离关注点和obj.Se

我试图将我的代码划分为模型和序列化程序,其思想是有一个定义的序列化程序来处理所有json职责,即分离关注点。我还希望能够调用模型对象
obj.Serialize()
,以获取序列化程序结构obj,然后对其进行封送处理。因此,我提出了以下设计。为了避免循环导入,我必须在序列化程序中使用接口,这导致在模型中使用getter。我已经读到getter/setter不是惯用的go代码,我不希望所有模型都有“样板”getter代码。对于我想要完成的任务,有没有更好的解决方案,请记住我想要分离关注点和
obj.Serialize()

models/a.go

import "../serializers"

type A struct {
  name string
  age int // do not marshal me
}

func (a *A) Name() string {
  return a.name
}

// Serialize converts A to ASerializer
func (a *A) Serialize() interface{} {
    s := serializers.ASerializer{}
    s.SetAttrs(a)
    return s
}
// AInterface used to get Post attributes
type AInterface interface {
  Name() string
}

// ASerializer holds json fields and values
type ASerializer struct {
  Name `json:"full_name"`
}

// SetAttrs sets attributes for PostSerializer
func (s *ASerializer) SetAttrs(a AInterface) {
  s.Name = a.Name()
}
序列化程序/a.go

import "../serializers"

type A struct {
  name string
  age int // do not marshal me
}

func (a *A) Name() string {
  return a.name
}

// Serialize converts A to ASerializer
func (a *A) Serialize() interface{} {
    s := serializers.ASerializer{}
    s.SetAttrs(a)
    return s
}
// AInterface used to get Post attributes
type AInterface interface {
  Name() string
}

// ASerializer holds json fields and values
type ASerializer struct {
  Name `json:"full_name"`
}

// SetAttrs sets attributes for PostSerializer
func (s *ASerializer) SetAttrs(a AInterface) {
  s.Name = a.Name()
}

看起来您实际上是在尝试在内部结构和json之间进行转换。我们可以从利用json库开始

如果您希望某些库以某种方式处理结构字段,则可以使用标记。此示例显示了json标记如何告诉json不要将字段
age
封送到json中,如果字段
jobTitle
不为空,则只添加该字段,并且该字段
jobTitle
在json中实际上被称为
title
。当go中的结构包含大写(导出)字段,但连接到的json api使用小写键时,此重命名功能非常有用

type A struct {
  Name     string
  Age      int `json:"-"`// do not marshal me
  location      string // unexported (private) fields are not included in the json marshal output
  JobTitle string `json:"title,omitempty"` // in our json, this field is called "title", but we only want to write the key if the field is not empty.
}
如果您需要预计算一个字段,或者只是在一个结构的json输出中添加一个不是该结构的成员的字段,我们可以通过一些魔术来做到这一点。当json对象再次解码为golang结构时,不适合的字段(在检查重命名字段和大小写差异后)将被忽略

// AntiRecursionMyStruct avoids infinite recursion in MashalJSON. Only intended for the json package to use.
type AntiRecursionMyStruct MyStruct

// MarshalJSON implements the json.Marshaller interface. This lets us marshal this struct into json however we want. In this case, we add a field and then cast it to another type that doesn't implement the json.Marshaller interface, and thereby letting the json library marshal it for us.
func (t MyStruct) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct {
        AntiRecursionMyStruct
        Kind string // the field we want to add, in this case a text representation of the golang type used to generate the struct
    }{
        AntiRecursionMyStruct: AntiRecursionMyStruct(t),
        Kind: fmt.Sprintf("%T", MyStruct{}),
    })
}
请记住,json将只包括导出(大写)的结构成员。我已经多次犯过这个错误

一般来说,如果事情看起来太复杂,可能有更好的方法