如何将不同的请求json主体解组为通用接口

时间:2017-03-19 13:52:51

标签: json go interface

当我想将不同的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`
}

如果我有很多结构,例如fetchapt ..我必须为每个模块实现每个处理程序。还有另外一种方法吗?像贝娄一样

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

1 个答案:

答案 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