最近在写个 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"`
1
TommyLemon 2018-11-12 16:25:13 +08:00 1
|
2
zjsxwc 2018-11-12 16:28:23 +08:00
这个反爬虫 666 !
|
3
zjsxwc 2018-11-12 16:33:28 +08:00 1
|
4
katsusan OP @TommyLemon 是的,确认了的确不符合规范,但不知道 valve 这样做的用意是啥
|
5
TommyLemon 2018-11-12 16:39:43 +08:00
@katsusan 估计就不是按照 application/json 格式返回的,可能是 text/plain 这种
|
6
chengfeng1992 2018-11-12 16:39:45 +08:00 1
dota2 ?
这个是不是考虑自己先把 json 字符串特殊处理一下呢? 比如,trim 后直接把 ``` "abilities": ``` 全 remove 掉,然后用 ``` [] ``` 括起来。 |
7
katsusan OP @zjsxwc 动态语言下的替换指的是正则匹配后替换还是,有思路的话 golang 应该实现也没问题。
主要是询问有没有碰到过或者见过第三方 json 库支持这种情况的。 |
8
zhujinliang 2018-11-12 16:44:05 +08:00 via iPhone
这种用遍历 Token 自己搞吧
|
9
katsusan OP @TommyLemon 是按照 json 返回的,它有个?format=xxx 参数,不指定的话就返回 json,参考网站:
http://steamwebapi.azurewebsites.net/ |
10
TommyLemon 2018-11-12 16:45:52 +08:00
看到上面的链接,随便输入 key 点了下,发现 Response Header 里:
content-type: text/html |
11
TommyLemon 2018-11-12 16:46:49 +08:00
@katsusan 那就很奇怪了,它的库有问题啊,居然支持在同一层级有同名的 key,或者压根就没用 JSON 库解析过,直接拼出来字符串返回
|
12
zjsxwc 2018-11-12 16:48:19 +08:00 1
@katsusan
字符串替换都可以。 golang 你也手动替换成合法的 json 吧, 1. 把第一个`"abilities":[` 替换为 `"abilities":[[` 2. 把最后一个`"ability_level":1}]` 替换为 `"ability_level":1}]]` 3. 把剩下的 `"abilities":[` 替换为 `[` |
13
katsusan OP @TommyLemon key 要去 steam 申请的,随便填应该会返回一个 forbidden 页面,所以是 html 格式,在 chrome 里可以直接看到:
``` Forbidden Access is denied. Retrying will not help. Please verify your key= parameter. ``` |
14
ihongren 2018-11-12 16:50:48 +08:00
最外层是个数组吗?
|
15
qwertyzzz 2018-11-12 16:52:38 +08:00
dota2 ! 我记得有个 opendota 和 varendata 的
|
18
xqin 2018-11-12 17:28:20 +08:00
都不在同一层级, 有啥问题? 哪重复了?
一个在 "radiant" 节点下, 一个在 "dire" 节点下. 类似于下面这样, 你能说下面的 `hello` 是重复键? ``` { "a": { "hello": 123 }, "b": { "hello": 456 } } ``` https://imgur.com/a/sLZdgW1 |
19
TommyLemon 2018-11-12 17:32:56 +08:00
@katsusan 这个我知道,一般只要 Request 能到达接口,处理后业务错误也应该返回和正确结果格式一致的 Response。
它既然都提示 key 有问题了,就说明已经经过接口处理过了。 |
21
ccpp132 2018-11-12 18:27:24 +08:00
看看你用的 json 库有没有 sax 的接口,这种一般可行
|
23
xqin 2018-11-12 18:53:10 +08:00
@katsusan 不好意思, 看错了, 是我的那个 Chrome 插件解析之后,只剩 4 个了, 查看 原始的数据的时候, 里面是有很多个.
|
24
vishva 2018-11-12 19:01:13 +08:00
拿到 json 之后先别解析,将五个"abilities"字符串依次替换成"abilities0","abilities1"...再解析
|
25
mengzhuo 2018-11-12 19:25:20 +08:00 1
有个东西叫
json-to-go https://mholt.github.io/json-to-go/ type AutoGenerated struct { Abilities []struct { AbilityID int `json:"ability_id"` AbilityLevel int `json:"ability_level"` } `json:"abilities"` } |
26
gamexg 2018-11-12 21:47:48 +08:00 1
|
28
reus 2018-11-15 10:39:37 +08:00 1
这个不难处理,用标准库就行,稍微加点技巧
https://gist.github.com/reusee/2cf9de7bbf46e6049a798630002db54b 就是用 json.Decoder.Token 方法把 "abilities" 读掉,然后用 Decode 方法解码后面的数组,直到 Token 返回 '}' |