Golang Go语言中使用json解析库遇到的问题

发布于 1周前 作者 wuwangju 来自 Go语言

Golang Go语言中使用json解析库遇到的问题

一个请求 ISBN 查询 API 的服务,查询信息的字段是:

type info struct {
	ISBN       string `json:"isbn"`
	Title      string `json:"title"`
	Subtitle   string `json:"subtitle"`
	Pic        string `json:"pic"`
	Author     string `json:"author"`
	Summary    string `json:"summary"`
	Publisher  string `json:"publisher"`
	Pubplace   string `json:"pubplace"`
	Page       int    `json:"page"`
	Price      string `json:"price"`
	Binding    string `json:"binding"`
	Keyword    string `json:"keyword"`
	Edition    string `json:"edition"`
	Impression string `json:"impression"`
	Language   string `json:"language"`
	Format     string `json:"format"`
	Class      string `json:"class"`
}

这里的 page 最初我写了 string 类型,然后解析报错了json: cannot unmarshal number into Go value of type string

然后我改为了 int 类型,然后依然会时不时报错json: cannot unmarshal string into Go struct field info.page of type int???昨天报错了几次,之后却一直正常想复现都不行,今天又报错了。查验了那个 ISBN API 应该没有问题,给的 page 就是 integer

但是这里报错后却插入数据库了,逻辑是这样的:

func get(isbn string) (*info, error) {
	url := baseURL + isbn
	resp, err := nic.Get(url, nil)
	if err != nil {
		return nil, err
	}
t := &tmp{0, "", &info{}}
err = resp.JSON(t)   //***************************************** error here
if err != nil {
	return nil, err
}
if t.Status != 0 {
	return nil, errors.New(t.Msg)
}

return t.Result, nil

}

func query(c *mgo.Collection, isbn string) (*info, error) { data := &info{} c.Find(bson.M{“isbn”: isbn}).One(data)

if data.ISBN == "" {
	var err error
	data, err = get(isbn)
	if err != nil {
		return nil, err
	}
	err = c.Insert(data)
	if err != nil {
		return nil, err
	}
}
return data, nil

}

而且第一次报错后插入数据库的数据却是正确的,page 就是正确的 integer:

 {'isbn': '9787212053937', 'page': 236, 'price': '21.50', 'binding': '', 'keyword': '', 'edition': '', 'impression': '', 'language': '', 'format': '', 'class': ''}

orz


更多关于Golang Go语言中使用json解析库遇到的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

17 回复

我知道了,貌似是 mgo 报的错

更多关于Golang Go语言中使用json解析库遇到的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果是因为字段类型不一致,可以试试 json.Number

估计有 number 有 string




感谢回复,我又测试了一下,果然这个 zz 的 API 第一次请求返回 int 之后都返回 string,服了…

<br>2019/05/30 19:08:29 int<br>2019/05/30 19:08:29 {"status":0,"msg":"ok","result":{"title":"课本全解( 5 年级上)","<br>author":null,"subtitle":null,"pubdate":" 2012-7","page":" 236","price":" 21.50 元","s ummary":"","pic":"http:\/\/<a target="_blank" href="http://api.jisuapi.com" rel="nofollow noopener">api.jisuapi.com</a>\/isbn\/\/upload\/3663\/3662449.","isbn":"9787212053928","isbn10":"7212053929","sellerlist":[{"seller":"douban","price":"21.50"}]}}<br>2019/05/30 19:08:29 89<br>2019/05/30 19:08:29 json: cannot unmarshal string into Go struct field info.page of type int<br><br>[GIN] 2019/05/30 - 19:08:29 | 200 | 1.5377224s | 127.0.0.1 | POST /api/v1/isbn-query<br>2019/05/30 19:10:06 int<br>2019/05/30 19:10:06 {"status":0,"msg":"ok","result":{"title":"课本全解( 5 年级上)","<br>subtitle":null,"pic":"http:\/\/<a target="_blank" href="http://api.jisuapi.com" rel="nofollow noopener">api.jisuapi.com</a>\/isbn\/upload\/3663\/3662449.","author":null,"summary":null,"publisher":null,"pubplace":null,"pubdate":" 2012-7","page":236,"price":"21.50","binding":null,"isbn":"9787212053928","isbn10":"7212053929","keyword":null,"edition":null,"impression":null,"language":null,"format":null,"class":null,"sellerlist":[{"seller":"douban","price":"21.50"}]}}<br>[GIN] 2019/05/30 - 19:10:06 | 200 | 176.5282ms | 127.0.0.1 | POST /api/v1/isbn-query<br>[GIN] 2019/05/30 - 19:10:16 | 200 | 0s | 127.0.0.1 | POST /api/v1/isbn-query<br>

初学 golang,正好看到这个问题,请教下,这样类型不确定的 json 要怎么解析?



json.Number 有点问题,page 字段可能返回空"page": null,,用 json.Number 就报错了failed to convert json.Number to a number:,改成了 interface{}暂时测试没什么问题


我这里把 page 定义成空接口类型了,假如之后需要这个确定类型的话再做类型断言就行

对于要兼容这种奇葩的字段,可以这样:

type Number int64

然后给这个 Number 实现 json.Unmarshaler 接口来自定义解析逻辑。

感谢回复,学到了

感谢,这个方法好。

我倒是挺好奇这个 api 是怎么实现一会儿返回 int 一会儿返回 string 的…

动态类型语言比较容易出现这样的情况,当然,还是看使用者的水平

最理想是 interface{},什么都能收,然后根据具体类型做处理


最逗的是这个 API 文档告诉我类型是 string,然后第一次请求返回 string 之后请求全是 int,可能跟服务端某些缓存机制有关

https://github.com/json-iterator/go 这个包有个 Any 类型,可以试下

在Go语言中,使用JSON解析库(如标准库中的encoding/json)时遇到问题,通常可以归结为几类常见错误。以下是一些排查和解决这些问题的建议:

  1. 数据格式错误:确保JSON数据格式正确,包括正确的引号、逗号、括号等。可以使用在线JSON验证工具检查数据的有效性。

  2. 类型不匹配:Go结构体中的字段类型必须与JSON数据中的类型一致。例如,JSON中的数字不能映射到Go中的字符串类型。

  3. 标签使用不当:结构体字段上的json标签用于指定JSON字段名。如果标签使用错误(如拼写错误、大小写不匹配),将导致解析失败。

  4. 嵌套结构:对于复杂的嵌套JSON结构,确保Go中的结构体也正确嵌套,并且每个字段都正确映射。

  5. 空值处理:JSON中的null值在Go中可能无法直接映射到某些类型(如非指针的基本类型)。使用指针或自定义Unmarshal方法处理空值。

  6. 错误处理:确保在解析JSON时检查并处理Unmarshal函数返回的错误。

  7. 性能问题:对于大型JSON数据,考虑使用流解析(如encoding/json.Decoder)以提高性能。

如果以上建议仍未解决问题,建议提供具体的错误信息、JSON数据示例和Go代码片段,以便进一步分析问题所在。同时,查阅官方文档和社区资源也是解决JSON解析问题的好方法。

回到顶部