Golang解析JSON值无效的问题如何解决
Golang解析JSON值无效的问题如何解决 我正在做一个项目,但不确定这里出了什么问题。我想只打印响应中的URL。
以下是示例JSON响应,但我只想打印URL的值。当我尝试在代码中编辑为“page.url”时,它不起作用。
"page": {
"country": "US",
"server": "cloudflare",
"domain": "www.hackerone.com",
"ip": "2606:4700::6810:6334",
"mimeType": "text/html",
"asnname": "CLOUDFLARENET, US",
"asn": "AS13335",
"url": "https://www.hackerone.com/?mkt_tok=MTY4LU5BVS03MzIAAAF-rKuriE5nHtVheqeA84AIT2tevNUnsoT9TxntfJhmpZiMVBpnp-OsEoZ0SVNYn5ZrrhGGU_54HmE3O5XSFyxa5ZDkja-Yt60twui1SRYW8m0",
"status": "200"
},
以下是我的代码:
package main
import(
"fmt"
"net/http"
"io/ioutil"
"encoding/json"
)
type Data []struct {
Url string `json:"page,url"`
}
func main() {
url := "https://urlscan.io/api/v1/search/?q=hackerone.com"
client := &http.Client{}
req, err := http.NewRequest("GET" , url , nil)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("API-Key", "")
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body)) //this will print all the output
var u Data
err = json.Unmarshal(body, &u)
f := make([]string, 0)
for _, u := range u {
f = append(f,u.Url)
}
fmt.Println(f)
}
更多关于Golang解析JSON值无效的问题如何解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html
6 回复
你好 @osibyte,
可能是一个简单的原因——json:"page,url" 中包含了一个逗号,我认为这里应该写作 json:"page.url"。
你需要一个能正确表示JSON数据的Go结构体。
type Data struct {
Results []struct {
IndexedAt time.Time `json:"indexedAt"`
Task struct {
Visibility string `json:"visibility"`
Method string `json:"method"`
Domain string `json:"domain"`
Time time.Time `json:"time"`
UUID string `json:"uuid"`
URL string `json:"url"`
Tags []string `json:"tags"`
} `json:"task"`
Stats struct {
UniqIPs int `json:"uniqIPs"`
ConsoleMsgs int `json:"consoleMsgs"`
UniqCountries int `json:"uniqCountries"`
DataLength int `json:"dataLength"`
EncodedDataLength int `json:"encodedDataLength"`
Requests int `json:"requests"`
} `json:"stats"`
Page struct {
Country string `json:"country"`
Server string `json:"server"`
Domain string `json:"domain"`
IP string `json:"ip"`
MimeType string `json:"mimeType"`
Asnname string `json:"asnname"`
Asn string `json:"asn"`
URL string `json:"url"`
Status string `json:"status"`
} `json:"page"`
ID string `json:"_id"`
Sort []interface{} `json:"sort"`
Result string `json:"result"`
Screenshot string `json:"screenshot"`
} `json:"results"`
Total int `json:"total"`
Took int `json:"took"`
HasMore bool `json:"has_more"`
}
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"time"
"net/http"
)
type Data struct {
Results []struct {
IndexedAt time.Time `json:"indexedAt"`
Task struct {
Visibility string `json:"visibility"`
Method string `json:"method"`
Domain string `json:"domain"`
Time time.Time `json:"time"`
UUID string `json:"uuid"`
URL string `json:"url"`
Tags []string `json:"tags"`
} `json:"task"`
Stats struct {
UniqIPs int `json:"uniqIPs"`
ConsoleMsgs int `json:"consoleMsgs"`
UniqCountries int `json:"uniqCountries"`
DataLength int `json:"dataLength"`
EncodedDataLength int `json:"encodedDataLength"`
Requests int `json:"requests"`
} `json:"stats"`
Page struct {
Country string `json:"country"`
Server string `json:"server"`
Domain string `json:"domain"`
IP string `json:"ip"`
MimeType string `json:"mimeType"`
Asnname string `json:"asnname"`
Asn string `json:"asn"`
URL string `json:"url"`
Status string `json:"status"`
} `json:"page"`
ID string `json:"_id"`
Sort []interface{} `json:"sort"`
Result string `json:"result"`
Screenshot string `json:"screenshot"`
} `json:"results"`
Total int `json:"total"`
Took int `json:"took"`
HasMore bool `json:"has_more"`
}
func main() {
url := "https://urlscan.io/api/v1/search/?q=hackerone.com"
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("API-Key", "")
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var u Data
err = json.Unmarshal(body, &u)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
f := make([]string, len(u.Results))
for _, r := range u.Results {
f = append(f, r.Page.URL)
fmt.Println(r.Page.URL)
fmt.Println(r.Task.URL)
}
}
天啊,兄弟,我都不知道该怎么感谢你。我卡在这个问题上已经两个多月了。
非常感谢。
这是包含更多修复的完整代码 😊
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"time"
"net/http"
)
type Data struct {
Results []struct {
IndexedAt time.Time `json:"indexedAt"`
Task struct {
Visibility string `json:"visibility"`
Method string `json:"method"`
Domain string `json:"domain"`
Time time.Time `json:"time"`
UUID string `json:"uuid"`
URL string `json:"url"`
Tags []string `json:"tags"`
} `json:"task"`
Stats struct {
UniqIPs int `json:"uniqIPs"`
ConsoleMsgs int `json:"consoleMsgs"`
UniqCountries int `json:"uniqCountries"`
DataLength int `json:"dataLength"`
EncodedDataLength int `json:"encodedDataLength"`
Requests int `json:"requests"`
} `json:"stats"`
Page struct {
Country string `json:"country"`
Server string `json:"server"`
Domain string `json:"domain"`
IP string `json:"ip"`
MimeType string `json:"mimeType"`
Asnname string `json:"asnname"`
Asn string `json:"asn"`
URL string `json:"url"`
Status string `json:"status"`
} `json:"page"`
ID string `json:"_id"`
Sort []interface{} `json:"sort"`
Result string `json:"result"`
Screenshot string `json:"screenshot"`
} `json:"results"`
Total int `json:"total"`
Took int `json:"took"`
HasMore bool `json:"has_more"`
}
func main() {
url := "https://urlscan.io/api/v1/search/?q=hackerone.com"
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("API-Key", "")
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var u Data
err = json.Unmarshal(body, &u)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
f := make([]string, len(u.Results))
for _, r := range u.Results {
f = append(f, r.Page.URL)
fmt.Println(r.Page.URL)
fmt.Println(r.Task.URL)
}
}
你的问题在于结构体标签 json:"page,url" 的写法不正确。对于嵌套的JSON字段,应该使用 json:"page.url",但Go的标准库 encoding/json 不支持这种点分隔的路径语法。你需要定义一个匹配JSON结构层次的结构体。
以下是修正后的代码:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
// 定义匹配JSON结构的类型
type Response struct {
Results []struct {
Page struct {
URL string `json:"url"`
} `json:"page"`
} `json:"results"`
}
func main() {
url := "https://urlscan.io/api/v1/search/?q=hackerone.com"
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Println(err)
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("API-Key", "")
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
return
}
// 解析JSON响应
var response Response
err = json.Unmarshal(body, &response)
if err != nil {
fmt.Println("解析JSON失败:", err)
return
}
// 提取所有URL
urls := make([]string, 0)
for _, result := range response.Results {
urls = append(urls, result.Page.URL)
}
fmt.Println("提取的URL列表:")
for i, url := range urls {
fmt.Printf("%d: %s\n", i+1, url)
}
}
如果你的JSON响应结构不同,这里还有一个更通用的解决方案,使用 map[string]interface{}:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://urlscan.io/api/v1/search/?q=hackerone.com"
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Println(err)
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("API-Key", "")
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
return
}
// 解析为map
var data map[string]interface{}
err = json.Unmarshal(body, &data)
if err != nil {
fmt.Println("解析JSON失败:", err)
return
}
// 根据实际JSON结构提取URL
if results, ok := data["results"].([]interface{}); ok {
urls := make([]string, 0)
for _, result := range results {
if resultMap, ok := result.(map[string]interface{}); ok {
if page, ok := resultMap["page"].(map[string]interface{}); ok {
if url, ok := page["url"].(string); ok {
urls = append(urls, url)
}
}
}
}
fmt.Println("提取的URL列表:")
for i, url := range urls {
fmt.Printf("%d: %s\n", i+1, url)
}
}
}
第一个解决方案使用具体类型定义,代码更清晰安全;第二个解决方案更灵活,能处理各种JSON结构。根据你的实际JSON响应结构选择合适的方法。


