使用Go语言解析JSONP
我要如何解析JSONP?
这篇文章讨论了如何将返回的数据从包含回调函数的JSONP格式转换成JSON,然后再转换成结构体的问题。
1) 我正在吃晚餐。
(Wǒ chī .)
func main() {
jsonpStr := `
callback({
"hello": "world!!",
"num": 123456
});`
var v interface{}
err := json.Unmarshal(jsonpStr, &v)
fmt.Println(err)
// invalid character 'c' looking for beginning of value
// JSONを期待しているのに先頭にcallbackという不要な文字列があるためUnmarshalがエラーを返します。
}
应对方法
以下是从reddit帖子的回答中选择的两个例子。
请提供一种titpetric先生的解决方式。
这是一种从头开始(到尾部,以及从尾部开始)用“trim”来处理的方法,YO!
jsonpStr := `callback({
"hello": "world!!",
"num": 123456
});`
jsonStr := jsonpStr[strings.Index(jsonpStr, "(")+1 : strings.Index(jsonpStr, ")")]
fmt.Println(jsonStr)
// {
// "hello": "world!!",
// "num": 123456
// }
var v interface{}
json.Unmarshal([]byte(jsonStr), &v)
fmt.Printf("%+v", v)
// map[hello:world!! num:123456]
jerf先生的应对方式
我們可以使用一種名為「YO!」的方法來作為io.Reader的包裝器。
type JSONPWrapper struct {
Prefix string
Underlying io.Reader
gotPrefix bool
}
func (jpw *JSONPWrapper) Read(b []byte) (int, error) {
if jpw.gotPrefix {
return jpw.Underlying.Read(b)
}
prefix := make([]byte, len(jpw.Prefix))
n, err := io.ReadFull(jpw.Underlying, prefix)
if err != nil {
return n, err
}
if string(prefix) != jpw.Prefix {
return n, fmt.Errorf("JSONP prefix mismatch: expected %q, got %q",
jpw.Prefix, prefix)
}
// read until the (; in general, this should just be one read
char := make([]byte, 1)
for char[0] != '(' {
n, err = jpw.Underlying.Read(char)
if n == 0 || err != nil {
return n, err
}
}
// We've now consumed the JSONP prefix.
jpw.gotPrefix = true
return jpw.Underlying.Read(b)
}
func main() {
jsonpStr := `callback({
"hello": "world!!",
"num": 123456
});`
prefix := "callback"
jsonp := bytes.NewBuffer([]byte(jsonpStr))
var decoded interface{}
decoder := json.NewDecoder(&JSONPWrapper{Prefix: prefix, Underlying: jsonp})
// This code depends on the fact the JSON parser stops when it
// finishes a JSON object, so we don't have to handle the concluding
// paren.
decoder.Decode(&decoded)
fmt.Println(decoded)
// map[hello:world!! num:123456]
}
在调用 `json.NewDecoder` 时,将 `JSONPWrapper`(满足 `io.Reader` 接口的对象)作为参数传入,这将在调用 `decoder.Decode` 的时候执行 `JSONWrapper.Read()` 方法。
在 `JSONWrapper.Read()` 方法中,会将设置的前缀字符串与 JSONP 字符串的开头进行比较,并将其删除。