json 的键重复问题

2018-11-12 16:17:59 +08:00
 katsusan

最近在写个 steam 的第三方 api,其中有个接口是返回当前联赛中的比赛详细资料。url 是下面这个:

https://api.steampowered.com/IDOTA2Match_570/GetLiveLeagueGames/v1?key=<apikey>

但它返回的 json 里英雄描述技能升级的 key 是重复的,这个应该是不符合 json 编码标准的吧(没想到浓眉大眼的沃尔沃也干了),例如下:

"abilities":[  // <-这样的"abilities"键总共有 5 个(代表 5 个英雄的技能升级情况)
{
"ability_id":5106,   //唯一技能 ID
"ability_level":2  //技能等级
},
{
"ability_id":5107,
"ability_level":3
}
]
,
"abilities":[
{
"ability_id":5082,
"ability_level":3
},
{
"ability_id":5083,
"ability_level":2
}
]
,
"abilities":[
{
"ability_id":5122,
"ability_level":3
},
{
"ability_id":5123,
"ability_level":2
},
{
"ability_id":5125,
"ability_level":1
}
]

我尝试在结构体里用相同的 json tag 指定不同的字段但自带的 json 包好像解析不出来,求知道的大佬指点下。

	Abilities1 []struct {
		AbilityID    uint16 `json:"ability_id"`
		AbilityLevel uint8  `json:"ability_level"`
	} `json:"abilities"`
	Abilities2 []struct {
		AbilityID    uint16 `json:"ability_id"`
		AbilityLevel uint8  `json:"ability_level"`
	} `json:"abilities"`
5740 次点击
所在节点    Go 编程语言
28 条回复
TommyLemon
2018-11-12 16:25:13 +08:00
这都不是合法的 JSON,解析后就直接最后一个把上面的全覆盖了。
你把这段 JSON 复制粘贴到这个网站试试,用的是 js 原生的 JSON.parse 解析
http://apijson.org/
zjsxwc
2018-11-12 16:28:23 +08:00
这个反爬虫 666 !
zjsxwc
2018-11-12 16:33:28 +08:00
@zjsxwc

如果是动态语言,简单字符串替换下把`abilities`替换为 `abilities__<index_num>`然后就可以处理了,

golang 这种碰到就难搞了
katsusan
2018-11-12 16:37:53 +08:00
@TommyLemon 是的,确认了的确不符合规范,但不知道 valve 这样做的用意是啥
TommyLemon
2018-11-12 16:39:43 +08:00
@katsusan 估计就不是按照 application/json 格式返回的,可能是 text/plain 这种
chengfeng1992
2018-11-12 16:39:45 +08:00
dota2 ?

这个是不是考虑自己先把 json 字符串特殊处理一下呢?

比如,trim 后直接把 ``` "abilities": ``` 全 remove 掉,然后用 ``` [] ``` 括起来。
katsusan
2018-11-12 16:42:21 +08:00
@zjsxwc 动态语言下的替换指的是正则匹配后替换还是,有思路的话 golang 应该实现也没问题。
主要是询问有没有碰到过或者见过第三方 json 库支持这种情况的。
zhujinliang
2018-11-12 16:44:05 +08:00
这种用遍历 Token 自己搞吧
katsusan
2018-11-12 16:45:01 +08:00
@TommyLemon 是按照 json 返回的,它有个?format=xxx 参数,不指定的话就返回 json,参考网站:
http://steamwebapi.azurewebsites.net/
TommyLemon
2018-11-12 16:45:52 +08:00
看到上面的链接,随便输入 key 点了下,发现 Response Header 里:
content-type: text/html
TommyLemon
2018-11-12 16:46:49 +08:00
@katsusan 那就很奇怪了,它的库有问题啊,居然支持在同一层级有同名的 key,或者压根就没用 JSON 库解析过,直接拼出来字符串返回
zjsxwc
2018-11-12 16:48:19 +08:00
@katsusan

字符串替换都可以。

golang 你也手动替换成合法的 json 吧,

1. 把第一个`"abilities":[` 替换为 `"abilities":[[`

2. 把最后一个`"ability_level":1}]` 替换为 `"ability_level":1}]]`

3. 把剩下的 `"abilities":[` 替换为 `[`
katsusan
2018-11-12 16:50:36 +08:00
@TommyLemon key 要去 steam 申请的,随便填应该会返回一个 forbidden 页面,所以是 html 格式,在 chrome 里可以直接看到:
```
Forbidden
Access is denied. Retrying will not help. Please verify your
key=
parameter.
```
ihongren
2018-11-12 16:50:48 +08:00
最外层是个数组吗?
qwertyzzz
2018-11-12 16:52:38 +08:00
dota2 ! 我记得有个 opendota 和 varendata 的
katsusan
2018-11-12 17:02:35 +08:00
@ihongren 是的,以单场比赛为单位,json 附在 append 里了
katsusan
2018-11-12 17:03:58 +08:00
@qwertyzzz 是的,应该都是从 apisteam 里取得数据
xqin
2018-11-12 17:28:20 +08:00
都不在同一层级, 有啥问题? 哪重复了?
一个在 "radiant" 节点下, 一个在 "dire" 节点下.

类似于下面这样, 你能说下面的 `hello` 是重复键?
```
{
"a": {
"hello": 123
},

"b": {
"hello": 456
}
}
```


https://imgur.com/a/sLZdgW1
TommyLemon
2018-11-12 17:32:56 +08:00
@katsusan 这个我知道,一般只要 Request 能到达接口,处理后业务错误也应该返回和正确结果格式一致的 Response。
它既然都提示 key 有问题了,就说明已经经过接口处理过了。
katsusan
2018-11-12 17:44:43 +08:00
@xqin 每个 team 下都有 5 个 abilities 键

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/507056

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX