Golang新手处理JSON时遇到的常见问题

Golang新手处理JSON时遇到的常见问题 我正在尝试解码字节数组,但无法将数据解组到结构体中。当尝试访问数组的索引1时出现错误。有人能看出问题所在吗?

package main

import (
	"encoding/json"
	"fmt"
)

// Symbols struct
type symbols struct {
	SymbolID string `json:"symbol_id"`
}

func main() {

	

	var text = []byte(`[
		{
		  "symbol_id": "BITSTAMP_SPOT_BTC_USD",
		  "exchange_id": "BITSTAMP",
		  "symbol_type": "SPOT",
		  "asset_id_base": "BTC",
		  "asset_id_quote": "USD"
		},
		{
		  "symbol_id": "BITMEX_FTS_BTC_USD_170630",
		  "exchange_id" : "BITMEX",
		  "symbol_type": "FUTURES",
		  "future_delivery_time": "2017-06-30T10:00:00.000000Z"
		  "asset_id_base": "BTC",
		  "asset_id_quote": "USD",
		},
		{
		  "symbol_id": "DERIBIT_OPT_BTC_USD_170331_500_P",
		  "exchange_id": "DERIBIT",
		  "symbol_type": "OPTION",
		  "option_type_is_call": false,
		  "option_strike_price": 500.0,
		  "option_contract_unit": 1,
		  "option_exercise_style": "EUROPEAN",
		  "option_expiration_time": "2017-03-31T10:00:00.000000Z",
		  "asset_id_base": "BTC",
		  "asset_id_quote": "USD"
		}
	  ]`)

	var sym []symbols
	json.Unmarshal(text, &sym)

	fmt.Println(sym[1].SymbolID)

}

更多关于Golang新手处理JSON时遇到的常见问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

8 回复

是的,有错误的示例确实很烦人。

更多关于Golang新手处理JSON时遇到的常见问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我学到了另一种调试方法,谢谢。

在你的应用程序中,可以使用 https://github.com/clbanning/checkjson 来验证输入。或者你也可以在调用 json.Unmarshal 后使用 ResolveJSONError 函数来获取更详细的错误信息。

在处理某种格式的数据时,最好通过外部验证器来确保数据的有效性。例如,您可以将JSON数据通过python -mjson.tool进行管道传输,以验证其是否能输出相同的JSON。如果验证通过,继续调试您的代码!

我之前从未使用过 JSON 验证器,所以非常感谢。我会采纳您的建议,从返回错误值开始调试过程。有趣的是,我使用的 REST API 在其文档中提供的 JSON 片段就包含了这些错误。然而,当我尝试直接从他们的 API 请求中解组数据时,它却成功了。

你是什么意思?

检查 error 的返回值应该是众所周知的事情,也是一个好习惯,而使用 panic 处理错误虽然不够理想,但对于这么一小段代码来说已经足够好了。老实说,我认为这是理所当然的,甚至一开始都没运行你的代码就想先提出来。

使用的另一种技术只是受到谷歌的启发,在搜索框中输入"json validator"并选择了第一个结果。这里面没有太多深意……

最后,如果你检查 error 返回值并知道如何使用谷歌,大多数问题都很容易解决。让调试变得困难的,往往是忽略了一半可用数据。

你应该检查 json.Unmarshal 的返回值,它会告诉你这个信息:

invalid character '"' after object key:value pair

由于这个提示不太有用,我把你的 JSON 放到了 jsonlint.com 进行验证:

Error: Parse error on line 12:
...10:00:00.000000Z"		"asset_id_base": "BT
----------------------^
Expecting 'EOF', '}', ':', ',', ']', got 'STRING'

添加逗号后,出现了这个错误:

Error: Parse error on line 14:
..._id_quote": "USD",	},	{		"symbol_id":
----------------------^
Expecting 'STRING', got '}'

所以,去掉那个逗号后,JSON 就被报告为有效了。

你可以在 Go Playground 找到我修改后的版本:

https://play.golang.org/p/InYByDGGMOW

你的JSON数据格式有问题,导致解码失败。问题在于第二个对象的JSON语法错误:

  1. "future_delivery_time": "2017-06-30T10:00:00.000000Z"后面缺少逗号
  2. "asset_id_quote": "USD",后面多了一个逗号

修正后的JSON应该是:

var text = []byte(`[
    {
      "symbol_id": "BITSTAMP_SPOT_BTC_USD",
      "exchange_id": "BITSTAMP",
      "symbol_type": "SPOT",
      "asset_id_base": "BTC",
      "asset_id_quote": "USD"
    },
    {
      "symbol_id": "BITMEX_FTS_BTC_USD_170630",
      "exchange_id" : "BITMEX",
      "symbol_type": "FUTURES",
      "future_delivery_time": "2017-06-30T10:00:00.000000Z",
      "asset_id_base": "BTC",
      "asset_id_quote": "USD"
    },
    {
      "symbol_id": "DERIBIT_OPT_BTC_USD_170331_500_P",
      "exchange_id": "DERIBIT",
      "symbol_type": "OPTION",
      "option_type_is_call": false,
      "option_strike_price": 500.0,
      "option_contract_unit": 1,
      "option_exercise_style": "EUROPEAN",
      "option_expiration_time": "2017-03-31T10:00:00.000000Z",
      "asset_id_base": "BTC",
      "asset_id_quote": "USD"
    }
  ]`)

另外,建议在处理JSON解码时检查错误:

err := json.Unmarshal(text, &sym)
if err != nil {
    fmt.Println("JSON解码错误:", err)
    return
}

修正后,你的代码就能正确运行并输出:

BITMEX_FTS_BTC_USD_170630
回到顶部