如何正确解组 Golang 中的无键 JSON 数组?
How to Unmarshall key-less JSON array in Golang correctly?
我有 JSON 如下所示的数据:
[
{
"globalTradeID": 64201000,
"tradeID": 549285,
"date": "2016-11-11 23:51:58",
"type": "buy",
"rate": "10.33999779",
"amount": "0.02176472",
"total": "0.22504715"
},
{
"globalTradeID": 64200631,
"tradeID": 549284,
"date": "2016-11-11 23:48:39",
"type": "buy",
"rate": "10.33999822",
"amount": "0.18211700",
"total": "1.88308945"
}...
]
我试图通过定义一个类型来解组这个 JSON:
type TradeHistoryResponse []TradeHistoryInfo
type TradeHistoryInfo struct {
GlobalTradeID int64 `json:"globalTradeID"`
TradeID int64 `json:"tradeID"`
Date string `json:"date"`
Type string `json:"type"`
Rate float64 `json:"rate,string"`
Amount float64 `json:"amount,string"`
Total float64 `json:"total,string"`
}
然后拉取 JSON 数据:
//Read response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("[Poloniex] (doRequest) Failed to parse response for query to %s! (%s)", reqURL, err.Error())
}
//Convert JSON to struct
var THR TradeHistoryResponse
err = json.Unmarshal(body, &THR)
if err != nil {
return nil, fmt.Errorf("[Poloniex] (doRequest) Failed to convert response into JSON for query to %s! (%s)", reqURL, err.Error())
}
我收到以下错误:
(json: cannot unmarshal object into Go value of type poloniex.TradeHistoryResponse)
我猜为什么 Unmarshall 不起作用是因为数组是无键的?
很想就我如何最好地使它工作的问题得到一些澄清。
TradeHistoryResponse 是一个没有变量的类型,您必须创建一个 TradeHistoryResponse 类型的变量,如下所示:
var th TradeHistoryResponse
//Convert JSON to struct
err = json.Unmarshal(body, &th)
// ...
fmt.Printf("%+v\n", th)
我不认为像您预期的那样在 JSON 中解组数组实际上有效,但根据 encoding/json 的支持它确实有效。示例代码:
主包
import (
"encoding/json"
"fmt"
"log"
)
var mjs string = "[" +
"{" +
`"globalTradeID": 64201000,
"tradeID": 549285,
"date": "2016-11-11 23:51:58",
"type": "buy",
"rate": "10.33999779",
"amount": "0.02176472",
"total": "0.22504715"
},
{
"globalTradeID": 64200631,
"tradeID": 549284,
"date": "2016-11-11 23:48:39",
"type": "buy",
"rate": "10.33999822",
"amount": "0.18211700",
"total": "1.88308945"
}
]`
type TradeHistoryResponse []TradeHistoryInfo
type TradeHistoryInfo struct {
GlobalTradeID int64 `json:"globalTradeID"`
TradeID int64 `json:"tradeID"`
Date string `json:"date"`
Type string `json:"type"`
Rate float64 `json:"rate,string"`
Amount float64 `json:"amount,string"`
Total float64 `json:"total,string"`
}
func main() {
//Convert JSON to struct
var THR TradeHistoryResponse
err := json.Unmarshal([]byte(mjs), &THR)
if err != nil {
log.Fatal(err)
}
for _, v := range THR {
fmt.Printf("%+v", v)
fmt.Printf("\n")
}
}
这会按预期打印出所有值。因此,将 json 值转换为 float/int 也没有问题(这可能是我的第二个猜测)。
你确定你没有以任何方式修改 Body 吗?你给出的例子涵盖了所有边缘情况?
你能补充一下吗:
fmt.Println(string(body))
到第二个错误块并在此处记录它给出的错误。
你用的是哪个版本的go?我不排除 encoding/json 在不同版本之间发生变化的可能性。最后,如果确实是这种情况,那么简单的解决方法就是将您的响应作为字符串,删除所有空格并在“}'{”处拆分,如:
fmtBody := strings.Replace(string(body), "\n", "", -1)
fmtBody = strings.Replace(string(fmtBody), "\w", "", -1)
fmtBody = strings.Replace(string(fmtBody), "[", "", -1)
fmtBody = strings.Replace(string(fmtBody), "]", "", -1)
var goArrOfYourJsonsObj []String = strings.Split(fmtBody, "},{")
for k, _ := range goArrOfYourJsonsObj {
goArrOfYourJsonsObj[k] += "}"
}
现在你的 JSON 个对象被整齐地分成了一个 String 类型的 go 数组,它可以在 Unmarshall 中用作 []byte(val)。
我有 JSON 如下所示的数据:
[
{
"globalTradeID": 64201000,
"tradeID": 549285,
"date": "2016-11-11 23:51:58",
"type": "buy",
"rate": "10.33999779",
"amount": "0.02176472",
"total": "0.22504715"
},
{
"globalTradeID": 64200631,
"tradeID": 549284,
"date": "2016-11-11 23:48:39",
"type": "buy",
"rate": "10.33999822",
"amount": "0.18211700",
"total": "1.88308945"
}...
]
我试图通过定义一个类型来解组这个 JSON:
type TradeHistoryResponse []TradeHistoryInfo
type TradeHistoryInfo struct {
GlobalTradeID int64 `json:"globalTradeID"`
TradeID int64 `json:"tradeID"`
Date string `json:"date"`
Type string `json:"type"`
Rate float64 `json:"rate,string"`
Amount float64 `json:"amount,string"`
Total float64 `json:"total,string"`
}
然后拉取 JSON 数据:
//Read response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("[Poloniex] (doRequest) Failed to parse response for query to %s! (%s)", reqURL, err.Error())
}
//Convert JSON to struct
var THR TradeHistoryResponse
err = json.Unmarshal(body, &THR)
if err != nil {
return nil, fmt.Errorf("[Poloniex] (doRequest) Failed to convert response into JSON for query to %s! (%s)", reqURL, err.Error())
}
我收到以下错误:
(json: cannot unmarshal object into Go value of type poloniex.TradeHistoryResponse)
我猜为什么 Unmarshall 不起作用是因为数组是无键的?
很想就我如何最好地使它工作的问题得到一些澄清。
TradeHistoryResponse 是一个没有变量的类型,您必须创建一个 TradeHistoryResponse 类型的变量,如下所示:
var th TradeHistoryResponse
//Convert JSON to struct
err = json.Unmarshal(body, &th)
// ...
fmt.Printf("%+v\n", th)
我不认为像您预期的那样在 JSON 中解组数组实际上有效,但根据 encoding/json 的支持它确实有效。示例代码: 主包
import (
"encoding/json"
"fmt"
"log"
)
var mjs string = "[" +
"{" +
`"globalTradeID": 64201000,
"tradeID": 549285,
"date": "2016-11-11 23:51:58",
"type": "buy",
"rate": "10.33999779",
"amount": "0.02176472",
"total": "0.22504715"
},
{
"globalTradeID": 64200631,
"tradeID": 549284,
"date": "2016-11-11 23:48:39",
"type": "buy",
"rate": "10.33999822",
"amount": "0.18211700",
"total": "1.88308945"
}
]`
type TradeHistoryResponse []TradeHistoryInfo
type TradeHistoryInfo struct {
GlobalTradeID int64 `json:"globalTradeID"`
TradeID int64 `json:"tradeID"`
Date string `json:"date"`
Type string `json:"type"`
Rate float64 `json:"rate,string"`
Amount float64 `json:"amount,string"`
Total float64 `json:"total,string"`
}
func main() {
//Convert JSON to struct
var THR TradeHistoryResponse
err := json.Unmarshal([]byte(mjs), &THR)
if err != nil {
log.Fatal(err)
}
for _, v := range THR {
fmt.Printf("%+v", v)
fmt.Printf("\n")
}
}
这会按预期打印出所有值。因此,将 json 值转换为 float/int 也没有问题(这可能是我的第二个猜测)。
你确定你没有以任何方式修改 Body 吗?你给出的例子涵盖了所有边缘情况?
你能补充一下吗:
fmt.Println(string(body))
到第二个错误块并在此处记录它给出的错误。
你用的是哪个版本的go?我不排除 encoding/json 在不同版本之间发生变化的可能性。最后,如果确实是这种情况,那么简单的解决方法就是将您的响应作为字符串,删除所有空格并在“}'{”处拆分,如:
fmtBody := strings.Replace(string(body), "\n", "", -1)
fmtBody = strings.Replace(string(fmtBody), "\w", "", -1)
fmtBody = strings.Replace(string(fmtBody), "[", "", -1)
fmtBody = strings.Replace(string(fmtBody), "]", "", -1)
var goArrOfYourJsonsObj []String = strings.Split(fmtBody, "},{")
for k, _ := range goArrOfYourJsonsObj {
goArrOfYourJsonsObj[k] += "}"
}
现在你的 JSON 个对象被整齐地分成了一个 String 类型的 go 数组,它可以在 Unmarshall 中用作 []byte(val)。