为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
一只斗牛犬 2021-06-16 09:18:32
我正在编写一个 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 requesttype 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 中有类似的选择吗?
查看完整描述

3 回答

?
守着一只汪

TA贡献1872条经验 获得超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)

    // ...

}


查看完整回答
反对 回复 2021-06-28
  • 3 回答
  • 0 关注
  • 152 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信