json - 在 GO lang 中使用 API 时如何将 JSON 转换为 Go 类型定义

标签 json go struct

我正在构建一个使用 API 的应用程序,然后还将 json 数据保存到 go lang 结构中,稍后我将制作端点,为某些计算提供结果。我已经实现了使用 API,具有挑战性的部分是如何以 go 理解的方式保存数据。哪种方法合适?

下面是我发起请求时的JSON格式。 我感兴趣的key只有Time Series (1min)

JSON

{
    "Meta Data": {
        "1. Information": "Intraday (1min) prices and volumes",
        "2. Symbol": "MSFT",
        "3. Last Refreshed": "2018-05-24 16:00:00",
        "4. Interval": "1min",
        "5. Output Size": "Compact",
        "6. Time Zone": "US/Eastern"
    },
    "Time Series (1min)": {
        "2018-05-24 16:00:00": {
            "1. open": "98.3050",
            "2. high": "98.3600",
            "3. low": "98.2500",
            "4. close": "98.3100",
            "5. volume": "2377114"
        },
        "2018-05-24 15:59:00": {
            "1. open": "98.2900",
            "2. high": "98.3300",
            "3. low": "98.2900",
            "4. close": "98.3000",
            "5. volume": "137133"
        },
        "2018-05-24 15:58:00": {
            "1. open": "98.2900",
            "2. high": "98.3000",
            "3. low": "98.2600",
            "4. close": "98.2900",
            "5. volume": "135875"
        },
        "2018-05-24 15:53:00": {
            "1. open": "98.2750",
            "2. high": "98.2950",
            "3. low": "98.2600",
            "4. close": "98.2700",
            "5. volume": "77959"
        }
    }
}

代码

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "github.com/jmoiron/jsonq"
)

func main() {
    response, err := http.Get("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=1min&apikey=demo")
    if err != nil {
        fmt.Printf("The HTTP request failed with error %s\n", err)
    } else {
        data, _ := ioutil.ReadAll(response.Body)
        // fmt.Println(string(data))
    }
}

最佳答案

不幸的是,这些数据的结构很差,无法通过 golang JSON 基础设施轻松解码。

解码数据(如本示例)的一般方法是定义一个类型(或一组类型),其中包含您想要的结构并实现 json.Unmarshaler interface具有检查传入结构并手动填充所需结构的逻辑。

例如:

type Quote struct {
  Time                   string
  Open, High, Low, Close float32
  Volume                 int
}

type Quotes []Quote

func main() {
  qs := Quotes{}
  err := json.Unmarshal([]byte(jsonstr), &qs)
  if err != nil {
    panic(err)
  }
  fmt.Printf("%#v\n", qs)
}

const targetName = "Time Series (1min)"

func (qs *Quotes) UnmarshalJSON(bs []byte) error {
  // Unmarshal into a generic map
  obj := make(map[string]interface{})
  err := json.Unmarshal(bs, &obj)
  if err != nil {
    return err
  }

  // Find the target time series
  entries, ok := obj[targetName].(map[string]interface{})
  if !ok {
    return fmt.Errorf("cannot find entry with name %q", targetName)
  }

  // Parse a Quote object from each entry in the target object
  quotes := []Quote{}
  for timestamp, values := range entries {
    values, ok := values.(map[string]interface{})
    if !ok {
      return fmt.Errorf("value for %q is not an object", timestamp)
    }
    quote := Quote{}
    quote.Time = timestamp
    v, err := strconv.ParseFloat(values["1. open"].(string), 32)
    if err != nil {
      return err
    }
    quote.Open = float32(v)
    // Repeat for each of Close,High,Low,Volume...
    quotes = append(quotes, quote)
  }

  *qs = Quotes(quotes)
  return nil
}

关于json - 在 GO lang 中使用 API 时如何将 JSON 转换为 Go 类型定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50527606/

相关文章:

java - Spring - 发布 JSON 对象时指向父级的链接丢失

swift - 如何使用 [String : Any]? 作为可解码对象?

c - 访问其范围之外的本地声明的结构

go - 在 Codenvy 环境上运行 Go 服务器

sockets - 从套接字读取消息时如何获取字节顺序?

Golang 调用具有不同参数的方法

c - 指向结构内部的结构指针的空指针而不取消引用它

json - 如何从 http.Get 获取 JSON 响应

java - 如何返回具有 @Produces(MediaType.APPLICATION_JSON) 的响应字符串?

java - "Expected BEGIN_OBJECT but was STRING at line 1 column 1"