有没有办法从http响应中提取JSON而不必构建结构?

时间:2017-01-23 21:24:07

标签: json go

我所看到的所有方法都涉及构建结构并将数据解组到结构中。但是,如果我在数百个字段中获得JSON响应怎么办?我不想创建100个字段结构只是为了能够获得我想要的数据。来自Java背景,有简单的方法可以简单地将http响应作为字符串获取,然后将JSON字符串传递给允许轻松遍历的JSON对象。它非常无痛。 Go中有这样的东西吗?

伪代码中的Java示例:

participant_ids

4 个答案:

答案 0 :(得分:19)

Golang:从HTTP响应中获取JSON,而不使用结构作为帮助程序

这是我们遇到的典型情况。这是通过json.Unmarshal实现的。

这是一个简单的json

{"textfield":"I'm a text.","num":1234,"list":[1,2,3]}

被序列化以通过网络发送并在Golang结束时解组。

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"])
}

希望这有用。

答案 1 :(得分:2)

您也可以将其解组为map [string] interface {}

class User < ApplicationRecord
  validates :name, presence: true
  validates :email, presence: true
end

收到的json必须有一个对象作为最外层的元素。地图还可以包含列表或嵌套地图,具体取决于json。

答案 2 :(得分:2)

json.Unmarshal方法将解组为不包含原始JSON对象中所有字段的结构。换句话说,你可以挑选你的田地。下面是一个例子,其中选择了FirstName和LastName,并且从json字符串中忽略了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)
}

答案 3 :(得分:0)

这里的其他答案具有误导性,因为它们没有向您展示如果您 尝试在地图中更深入。这个例子工作得很好:

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])