最近在写个 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 ![]() |
![]() | 2 zjsxwc 2018-11-12 16:28:23 +08:00 这个反爬虫 666 ! |
![]() | 3 zjsxwc 2018-11-12 16:33:28 +08:00 ![]() |
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 ![]() 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 &nbs; 2018-11-12 16:48:19 +08:00 ![]() @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 asLw0P981N0M0TCC 2018-11-12 16:52:38 +08:00 dota2 ! 我记得有个 opendota 和 varendata 的 |
![]() | 18 O3YwA1ENkb7i35XJ 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 的接口,这种一般可行 |
![]() | 22 O3YwA1ENkb7i35XJ 2018-11-12 18:46:04 +08:00 @katsusan 你在 github 上发的那个数据, 并没有你说的这种情况. |
![]() | 23 O3YwA1ENkb7i35XJ 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 ![]() 有个东西叫 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 ![]() |
![]() | 28 reus 2018-11-15 10:39:37 +08:00 ![]() 这个不难处理,用标准库就行,稍微加点技巧 https://gist.github.com/reusee/2cf9de7bbf46e6049a798630002db54b 就是用 json.Decoder.Token 方法把 "abilities" 读掉,然后用 Decode 方法解码后面的数组,直到 Token 返回 '}' |