当我想将不同的json主体绑定到一个公共对象时,我遇到了一个问题。
type fetch struct {
Dest string
Src string
Flat bool
}
func (f *fetch) Build() string { return fmt.Sprintf("%s %s", f.Dest, f.Src) }
type apt struct {
Name string
State string
}
func (a *apt) Build() string { return fmt.Sprintf("%s %s", a.Name, a.State) }
func getFetch(w http.ResponseWriter, req *http.Request) {
var obj fetch
if err := json.NewDecoder(req.Body).Decode(&obj); err != nil{
// handle error
}
// handle obj.Build()
}
func getApt(w http.ResponseWriter, req *http.Request) {
// same as handler `getFetch`
}
如果我有很多结构,例如fetch
,apt
..我必须为每个模块实现每个处理程序。还有另外一种方法吗?像贝娄一样
// Module should implement `json.Marshaler` and `Unmarshaler` interface
type Module interface{
Build() string
}
func getCommon(w http.ResponseWriter, req *http.Request) {
var obj Module
if err := json.NewDecoder(req.Body).Decode(&obj); err != nil{
// handle error
}
// handle obj.Build()
}
但现在我不知道该怎么做.. 或者,如果有更好的方法吗?
更新:我看到了像这样的解决方案
type ReqJSON struct {
Type string
Data json.RawMessage
}
func getCommon(w http.ResponseWriter, req *http.Request) {
var obj ReqJSON
if err := json.NewDecoder(req.Body).Decode(&obj); err != nil{
// handle error
}
switch obj.Type {
case "fetch":
// decode obj.Data to `fetch`.
case "apt":
// decode obj.Data to `apt`.
case ...
}
}
但如果我有一个新模块,我必须经常重写getCommon
函数。
Update2:我解决了这个问题..
type Module interface{
Build() string
}
var Modules = map[string]func() Module{
"fetch": func() Module{return &fetch{}},
......
}
http处理程序中的:
typo reqJSON struct {
Type string
Data json.RawMessage
}
f, ok := Modules[req.Type]
if !ok{
//
}
m := f()
m.Build()
答案 0 :(得分:0)
您可以将JSON解码为map[string]interface{}
,例如:
func getCommon(w http.ResponseWriter, req *http.Request) {
var obj map[string]interface{}
if err := json.NewDecoder(req.Body).Decode(&obj); err != nil{
// handle error
}
// handle obj.Build()
}
或者,您可以使用json.RawMessage
,RawMessage是原始编码的JSON值,
它实现了Marshaler和Unmarshaler,GO - Package json