2017-09-18 55 views
-1

我想創建一個結構,其中一個字段可以舉行一些特定類型的數據,說intstringCustomType。我想解碼/編碼這個結構到/從JSON。 go/golang如何實現這一目標?編碼/解碼的多類型字段golang

例如,我有如下定義一個結構:

type MyData struct { 
    Name string         `json:"name"` 
    Value int32          `json:"value"` 
    Param <can be either int, string or CustomType> `json:"param"` 
} 

哪裏CustomType

type CustomType struct { 
    Custom bool `json:"custom"` 
} 

比方說,我需要解組以下JSONs上述結構MyData

{ 
    "name": "Hello", 
    "value": 32 
    "param": "World" 
} 

而這一個:

{ 
    "name": "Hello", 
    "value": 32 
    "param": 100 
} 

而這其中也:

{ 
    "name": "Hello", 
    "value": 32 
    "param": { 
    "custom": true 
    } 
} 

如何實現這一目標?

我可以在MyData上定義我自己的MarshalJSONUnmarshalJSON並實現此目的嗎?

或者是有定義的自定義類型的方式,說IntOrStringOrCustom並定義MyData

type MyData struct { 
    Name string    `json:"name"` 
    Value int32    `json:"value"` 
    Param IntOrStringOrCustom `json:"param"` 
} 

然後定義上IntOrStringOrCustomMarshalJSONUnmarshalJSON?我也看過json.RawMessage。我們能以某種方式在這裏使用它嗎?

使用interface{}的問題是,我將不得不編寫編碼/解碼邏輯,我試圖使用這些數據。或者有沒有一個這樣做的優雅方式interface{}

回答

1

已更新。 interface被自動編碼並解碼爲JSON。如果你想控制的類型,你可以在裏面添加特殊UnmarshalJSON並進行檢查:

type TheParam interface{} 

type MyData struct { 
    Name string `json:"name"` 
    Value int32 `json:"value"` 
    Param TheParam `json:"param"` 
} 

type myData MyData 

func (m *MyData) UnmarshalJSON(b []byte) error { 
    var mm myData 
    if err := json.Unmarshal(b, &mm); err != nil { 
     return err 
    } 
    switch mm.Param.(type) { 
    case float64, string, map[string]interface{}: 
     *m = MyData(mm) 
     return nil 
    default: 
     return InvalidFieldTypeError{value: mm.Param} 
    } 
    return nil 
} 

類型InvalidFieldTypeError可以方便地返回錯誤的類,而可以被定義爲:

type InvalidFieldTypeError struct { 
    value interface{} 
} 

func (e InvalidFieldTypeError) Error() string { 
    return fmt.Sprintf("Field type '%T' is not valid for MyData", e.value) 
} 

的整個例如:https://play.golang.org/p/MuW6gwSAKi

另外,我想推薦這篇文章https://attilaolah.eu/2013/11/29/json-decoding-in-go/

+0

感謝尤金。我希望能夠將解組僅限制爲指定的類型。使用和接口將導致對密鑰的任何類型的值進行成功解組。無論如何可以做到嗎? – Shahidh

+0

@ Shahidh是的。我已更新。你能檢查一下嗎? –

+0

再次感謝尤金。我們已經嘗試過這種方法,它工作。但問題是我們有很多結構需要進行驗證。所以,爲每個結構寫'MarshaJSON'和'UnmarshalJSON'並不是一個可行的解決方案。可悲的是,我無法將這些方法寫入'interface {}'。否則,我會寫它爲'TheParam'。 但是,我們發現了另一種方法,我們可以通過使用像https://github.com/asaskevich/govalidator這樣的包添加'validate'標籤來進行結構驗證。現在試試看。將更新,如果這是前進的方式 – Shahidh