在Golang中序列化模型

时间:2016-01-13 18:04:41

标签: serialization go

我试图将我的代码分成模型和序列化程序,并认为有定义的序列化程序可以处理所有json职责,即关注点的分离。我还希望能够调用模型对象obj.Serialize()来获取我可以编组的序列化器结构obj。因此,我提出了以下设计。为了避免循环导入,我不得不在序列化器中使用接口,这导致在我的模型中使用getter。我已经读到,getter / setter并不是惯用的代码,我宁愿没有"样板"我的模型遍布getter代码。是否有更好的解决方案来实现我想要完成的任务,请记住我想要分离关注点和obj.Serialize()

src/
    models/
        a.go
    serializers/
        a.go

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
}

serializers/a.go

// 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()
}

1 个答案:

答案 0 :(得分:3)

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

如果您希望某些库以某种方式处理结构字段,则有标记。此示例显示json标记如何告诉json永远不会将字段age封送到json中,并且如果字段jobTitle不为空,则仅添加字段jobTitle,并且实际调用字段title json中的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. } 。当go中的结构包含大写(导出)字段时,此重命名功能非常有用,但是您连接的json api使用小写键。

// 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输出中添加一个字段,我们可以用一些魔法来做到这一点。当json对象再次解码为golang结构时,不适合的字段(在检查重命名的字段和大小写差异之后)将被忽略。

od = OrderedDict([('totalSize', 3),
             ('done', True),
             ('records',
              [OrderedDict([('attributes',
                             OrderedDict([('type', 'Cust'),
                                          ('url',
                                           '/example/url/foo/bar/123')])),
                            ('Id', '4563456kjgfu4uyHHY3'),
                            ('Phone', None),
                            ('FirstName', 'Bill'),
                            ('LastName', 'Bob'),
                            ('Email', 'billbob@foo.com')]),
               OrderedDict([('attributes',
                             OrderedDict([('type', 'Cust'),
                                          ('url',
                                           '/example/url/foo/bar/234')])),
                            ('Id', 'KJ23jdkd889DKJD'),
                            ('Phone', '(444) 444-4444'),
                            ('FirstName', 'Amanda'),
                            ('LastName', 'Smith'),
                            ('Email', 'amanda.smith@bar.com')]),
               OrderedDict([('attributes',
                             OrderedDict([('type', 'Cust'),
                                          ('url',
                                           '/example/url/foo/bar/654')])),
                            ('Id', '23kkjKJkj2323KJ33'),
                            ('Phone', '(555) 555-5555'),
                            ('FirstName', 'Julie'),
                            ('LastName', 'jackson'),
                            ('Email', 'jjackson@test.com')])])])

请记住,json只包含您导出的(大写)结构成员。我多次犯了这个错误。

作为一般规则,如果某些事情看起来过于复杂,那么可能有更好的方法。