如何将 JSON 解组为由不同代码提供的 Go 结构?

我正在编写一个 Go 库,它将 JSON 解码为一个结构体。JSON 有一个相当简单的通用模式,但我希望这个库的使用者能够将额外的字段解码成他们自己的嵌入通用结构的结构,避免使用映射的需要。理想情况下,我只想对 JSON 解码一次。


目前它看起来像这样。(为简洁起见,删除了错误处理。)


JSON:


{ "CommonField": "foo",

  "Url": "http://example.com",

  "Name": "Wolf" }

图书馆代码:


// The base JSON request.

type BaseRequest struct {

    CommonField string

}


type AllocateFn func() interface{}

type HandlerFn func(interface{})


type Service struct {

    allocator AllocateFn

    handler HandlerFn

}   


func (Service *s) someHandler(data []byte) {

    v := s.allocator()

    json.Unmarshal(data, &v)

    s.handler(v)

}

应用程序代码:


// The extended JSON request

type MyRequest struct {

    BaseRequest

    Url string

    Name string

}


func allocator() interface{} {

    return &MyRequest{}

}


func handler(v interface{}) {

    fmt.Printf("%+v\n", v);

}


func main() {

    s := &Service{allocator, handler}

    // Run s, eventually s.someHandler() is called

}

我不喜欢这个设置的是allocator功能。所有实现都将简单地返回一个新的BaseRequest“子类型”。在更动态的语言中,我会传递MyRequestin的类型,并在库内实例化。我在 Go 中有类似的选择吗?


一只斗牛犬
浏览 153回答 3
3回答

守着一只汪

有几种方法可以处理这个问题。一个既简单又方便的想法是定义一个更丰富的请求类型,提供给处理程序,而不是传递原始类型。通过这种方式,您可以以友好的方式实现默认行为,并支持边缘情况。这也将避免在自定义类型上嵌入默认类型的需要,并允许您在不破坏客户端的情况下扩展功能。灵感:type Request struct {    CommonField string    rawJSON []byte}func (r *Request) Unmarshal(value interface{}) error {    return json.Unmarshal(r.rawJSON, value)}func handler(req *Request) {    // Use common data.    fmt.Println(req.CommonField)    // If necessary, poke into the underlying message.    var myValue MyType    err := req.Unmarshal(&myValue)    // ...}func main() {    service := NewService(handler)    // ...}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go