英文:
Is there a way to extract JSON from an http response without having to build structs?
问题
我看到的所有方法都涉及构建结构体并将数据解组到结构体中。但是,如果我收到的是具有数百个字段的JSON响应呢?我不想为了获取所需数据而创建100个字段的结构体。从Java背景来看,有简单的方法可以将HTTP响应直接作为字符串获取,然后将JSON字符串传递给允许轻松遍历的JSON对象。这非常简单。在Go语言中有类似的方法吗?
Java伪代码示例:
String json = httpResponse.getBody();
JsonObject object = new JsonObject(json);
object.get("desiredKey");
英文:
All of the ways I'm seeing involve building structs and unmarshalling the data into the struct. But what if I'm getting JSON responses with hundreds of fields? I don't want to have to create 100 field structs just to be able to get to the data I want. Coming from a Java background there are easy ways to simply get the http response as a string and then pass the JSON string into a JSON object that allows for easy traversal. It's very painless. Is there anything like this in Go?
Java example in pseudo code:
<!--code: java -->
String json = httpResponse.getBody();
JsonObject object = new JsonObject(json);
object.get("desiredKey");
答案1
得分: 33
Golang:在不使用结构体作为辅助工具的情况下从HTTP响应中获取JSON
这是我们经常遇到的典型场景。可以通过json.Unmarshal
来实现。
这是一个简单的JSON示例:
{"textfield":"我是一段文本。","num":1234,"list":[1,2,3]}
它被序列化后通过网络发送,并在Golang端进行反序列化。
package main
import (
"fmt"
"encoding/json"
)
func main() {
// 将下面这行替换为实际获取的响应体
responseBody := `{"textfield":"我是一段文本。","num":1234,"list":[1,2,3]}`
var data map[string]interface{}
err := json.Unmarshal([]byte(responseBody), &data)
if err != nil {
panic(err)
}
fmt.Println(data["list"])
fmt.Println(data["textfield"])
}
希望对你有帮助。
英文:
Golang: fetch JSON from an HTTP response without using structs as helpers
This is a typical scenario we come across. This is achieved by json.Unmarshal
.
Here is a simple json
<!-- language: javascript -->
{"textfield":"I'm a text.","num":1234,"list":[1,2,3]}
which is serialized to send across the network and unmarshaled at Golang end.
package main
import (
"fmt"
"encoding/json"
)
func main() {
// replace this by fetching actual response body
responseBody := `{"textfield":"I'm a text.","num":1234,"list":[1,2,3]}`
var data map[string]interface{}
err := json.Unmarshal([]byte(responseBody), &data)
if err != nil {
panic(err)
}
fmt.Println(data["list"])
fmt.Println(data["textfield"])
}
Hope this was helpful.
答案2
得分: 5
json.Unmarshal方法将解组为一个结构体,该结构体不包含原始JSON对象中的所有字段。换句话说,你可以挑选你需要的字段。以下是一个示例,其中FirstName和LastName是挑选的字段,而MiddleName被忽略了:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
func main() {
jsonString := []byte(`{"first_name": "John", "last_name": "Doe", "middle_name": "Anderson"}`)
var person Person
if err := json.Unmarshal(jsonString, &person); err != nil {
panic(err)
}
fmt.Println(person)
}
以上代码演示了如何使用json.Unmarshal方法将JSON字符串解组到Person结构体中,并只选择FirstName和LastName字段。
英文:
The json.Unmarshal method will unmarshal to a struct that does not contain all the fields in the original JSON object. In other words, you can cherry-pick your fields. Here is an example where FirstName and LastName are cherry-picked and MiddleName is ignored from the json string:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
func main() {
jsonString := []byte("{\"first_name\": \"John\", \"last_name\": \"Doe\", \"middle_name\": \"Anderson\"}")
var person Person
if err := json.Unmarshal(jsonString, &person); err != nil {
panic(err)
}
fmt.Println(person)
}
答案3
得分: 3
这里的其他答案是误导性的,因为它们没有展示如果你尝试在Map中深入一层会发生什么。这个示例足够好地工作:
package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
r, e := http.Get("https://github.com/manifest.json")
if e != nil {
panic(e)
}
body := map[string]interface{}{}
json.NewDecoder(r.Body).Decode(&body)
/*
[map[
id:com.github.android
platform:play
url:https://play.google.com/store/apps/details?id=com.github.android
]]
*/
fmt.Println(body["related_applications"])
}
但是,如果你尝试深入一层,它会失败:
/*
invalid operation: body["related_applications"][0] (type interface {} does not
support indexing)
*/
fmt.Println(body["related_applications"][0])
相反,你需要在每个深度级别上进行类型断言:
/*
map[
id:com.github.android
platform:play
url:https://play.google.com/store/apps/details?id=com.github.android
]
*/
fmt.Println(body["related_applications"].([]interface{})[0])
英文:
The other answers here are misleading, as they don't show you what happens if you try to go deeper in the Map. This example works fine enough:
package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
r, e := http.Get("https://github.com/manifest.json")
if e != nil {
panic(e)
}
body := map[string]interface{}{}
json.NewDecoder(r.Body).Decode(&body)
/*
[map[
id:com.github.android
platform:play
url:https://play.google.com/store/apps/details?id=com.github.android
]]
*/
fmt.Println(body["related_applications"])
}
but if you try to go one level deeper, it fails:
/*
invalid operation: body["related_applications"][0] (type interface {} does not
support indexing)
*/
fmt.Println(body["related_applications"][0])
Instead, you would need to assert type at each level of depth:
/*
map[
id:com.github.android
platform:play
url:https://play.google.com/store/apps/details?id=com.github.android
]
*/
fmt.Println(body["related_applications"].([]interface{})[0])
答案4
得分: 1
你可以将其解组为一个map[string]interface{}类型。
body, err := ioutil.ReadAll(resp.Body)
map := &map[string]interface{}{}
json.Unmarshal(body, map)
desiredValue := (*map)["desiredKey"]
接收到的JSON必须具有对象作为最外层元素。该map还可以包含列表或嵌套的map,具体取决于JSON的结构。
英文:
You can as well unmarshal it into a map[string]interface{}
body, err := ioutil.ReadAll(resp.Body)
map := &map[string]interface{}{}
json.Unmarshal(body, map)
desiredValue := map["desiredKey"]
The received json must have an object as the most outer element. The map can also contain lists or nested maps, depending on the json.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论