我试图将我的代码分成模型和序列化程序,并认为有定义的序列化程序可以处理所有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()
}
答案 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只包含您导出的(大写)结构成员。我多次犯了这个错误。
作为一般规则,如果某些事情看起来过于复杂,那么可能有更好的方法。