英文:
UnmarshalJSON results in stack overflow
问题
这是正确的链接:http://play.golang.org/p/-Kv3xAguDR。
这会导致堆栈溢出:http://play.golang.org/p/1-AsHFj51O。
我无法理解为什么会这样。在这种情况下,如何正确使用JSONUnmarshaler
接口?
package main
import (
//"bytes"
"encoding/json"
"fmt"
"strings"
)
type T interface {
Printer()
}
type A struct{ JA string }
func (t A) Printer() { fmt.Print("A") }
/*
func (t *A) UnmarshalJSON(data []byte) error {
i := A{}
dec := json.NewDecoder(bytes.NewReader(data))
if err := dec.Decode(&i); err != nil {
return err
}
i.Printer()
*t = i
return nil
}
*/
var vI []T
func main() {
vI = []T{&A{}}
get()
}
func get() {
dec := json.NewDecoder(strings.NewReader("[{\"JA\":\"OK\"}]"))
if err := dec.Decode(&vI); err != nil {
fmt.Print(err)
}
for _, v := range vI {
v.Printer()
}
}
英文:
This works: http://play.golang.org/p/-Kv3xAguDR.
This results in a stack overflow: http://play.golang.org/p/1-AsHFj51O.
I fail to understand why. What is the correct way use the JSONUnmarshaler
interface in this case?
package main
import (
//"bytes"
"encoding/json"
"fmt"
"strings"
)
type T interface {
Printer()
}
type A struct{ JA string }
func (t A) Printer() { fmt.Print("A") }
/*
func (t *A) UnmarshalJSON(data []byte) error {
i := A{}
dec := json.NewDecoder(bytes.NewReader(data))
if err := dec.Decode(&i); err != nil {
return err
}
i.Printer()
*t = i
return nil
}
*/
var vI []T
func main() {
vI = []T{&A{}}
get()
}
func get() {
dec := json.NewDecoder(strings.NewReader("[{\"JA\":\"OK\"}]"))
if err := dec.Decode(&vI); err != nil {
fmt.Print(err)
}
for _, v := range vI {
v.Printer()
}
}
答案1
得分: 2
这个
dec.Decode(&i)
将调用你的UnmarshalJSON
,然后再调用Decode
,以此类推。如果你需要解析你的JSON然后对其进行操作,一种简洁的技巧是声明一个本地类型,将数据解析到该类型中,然后再转换回你想要的类型:
// 类型a没有UnmarshalJSON方法。
type a A
i := a{}
dec := json.NewDecoder(bytes.NewReader(data))
if err := dec.Decode(&i); err != nil {
return err
}
// 转换回A类型。
tt := A(i)
tt.Printer()
*t = tt
// ...
Playground: http://play.golang.org/p/HWamV3MbvW.
类型a
没有方法(因此不会出现堆栈溢出),但可以转换为A
类型。
英文:
This
dec.Decode(&i)
will call your UnmarshalJSON
, which in turn will call Decode
, and so on. If you need to unmarshal your JSON and then do something with it, one neat technique is to declare a local type, unmarshal your data into it, and then convert back to your desired type:
// Type a has no UnmarshalJSON.
type a A
i := a{}
dec := json.NewDecoder(bytes.NewReader(data))
if err := dec.Decode(&i); err != nil {
return err
}
// Convert back to A.
tt := A(i)
tt.Printer()
*t = tt
// ...
Playground: http://play.golang.org/p/HWamV3MbvW.
The type a
has no methods (so no stack overflow), but is convertible to A
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论