2016-01-13 94 views
0

我试图将我的代码分离成模型和序列化器,并提供了处理所有json职责(即关注点分离)的定义序列化器。我也希望能够调用一个模型对象obj.Serialize()来获得串行器结构obj,然后我可以编组。因此,我想出了以下设计。为了避免循环导入,我不得不在我的序列化器中使用接口,这导致在我的模型中使用getter。我读过getters/setter不是惯用的go代码,我不希望在我的模型中使用“样板”getter代码。是否有更好的解决方案来实现我想要完成的任务,牢记我需要分离关注点和obj.Serialize()在Golang中序列化模型

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

回答

2

它看起来像你实际上是想你的内部结构和JSON之间的转换。我们可以从利用json库开始。

如果您希望某些库以某些方式处理您的struct字段,则会有标签。这个例子展示了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将只包含您的导出(大写)结构成员。我多次犯了这个错误。

作为一般规则,如果某件事看起来太复杂,那么可能有更好的方法来做到这一点。