2016-01-13 40 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將只包含您的導出(大寫)結構成員。我多次犯了這個錯誤。

作爲一般規則,如果某件事看起來太複雜,那麼可能有更好的方法來做到這一點。