c# - 如何使用来自 Yahoo Api 的索引解析 json 数组
问题描述
鉴于来自 Yahoo API 的此响应,我正在尝试使用 Newtonsoft.Json 和 ASP.NET / C# 解析播放器。我还想检查最后的值count
。
{
"fantasy_content": {
"xml:lang": "en-US",
"yahoo:uri": "/fantasy/v2/game/nfl/players",
"game": [
{
"game_key": "390",
"game_id": "390",
"name": "Football",
"code": "nfl",
"type": "full",
"url": "https://football.fantasysports.yahoo.com/f1",
"season": "2019",
"is_registration_over": 0,
"is_game_over": 0,
"is_offseason": 0
},
{
"players": {
"0": {
"player": [
[
{
"player_key": "390.p.30972"
},
{
"player_id": "30972"
},
{
"name": {
"full": "Saquon Barkley",
"first": "Saquon",
"last": "Barkley",
"ascii_first": "Saquon",
"ascii_last": "Barkley"
}
},
{
"editorial_player_key": "nfl.p.30972"
},
{
"editorial_team_key": "nfl.t.19"
},
{
"editorial_team_full_name": "New York Giants"
},
{
"editorial_team_abbr": "NYG"
},
{
"bye_weeks": {
"week": "11"
}
},
{
"uniform_number": "26"
},
{
"display_position": "RB"
},
{
"headshot": {
"url": "https://s.yimg.com/iu/api/res/1.2/RtPm7fdFHthz1._DrpkAqA--~C/YXBwaWQ9eXNwb3J0cztjaD0yMzM2O2NyPTE7Y3c9MTc5MDtkeD04NTc7ZHk9MDtmaT11bGNyb3A7aD02MDtxPTEwMDt3PTQ2/https://s.yimg.com/xe/i/us/sp/v/nfl_cutout/players_l/09242018/30972.png",
"size": "small"
},
"image_url": "https://s.yimg.com/iu/api/res/1.2/RtPm7fdFHthz1._DrpkAqA--~C/YXBwaWQ9eXNwb3J0cztjaD0yMzM2O2NyPTE7Y3c9MTc5MDtkeD04NTc7ZHk9MDtmaT11bGNyb3A7aD02MDtxPTEwMDt3PTQ2/https://s.yimg.com/xe/i/us/sp/v/nfl_cutout/players_l/09242018/30972.png"
},
{
"is_undroppable": "0"
},
{
"position_type": "O"
},
[],
{
"eligible_positions": [
{
"position": "RB"
}
]
},
[],
[],
[]
]
]
},
"1": {
"player": [
[
{
"player_key": "390.p.29238"
},
{
"player_id": "29238"
},
{
"name": {
"full": "Ezekiel Elliott",
"first": "Ezekiel",
"last": "Elliott",
"ascii_first": "Ezekiel",
"ascii_last": "Elliott"
}
},
{
"editorial_player_key": "nfl.p.29238"
},
{
"editorial_team_key": "nfl.t.6"
},
{
"editorial_team_full_name": "Dallas Cowboys"
},
{
"editorial_team_abbr": "Dal"
},
{
"bye_weeks": {
"week": "8"
}
},
{
"uniform_number": "21"
},
{
"display_position": "RB"
},
{
"headshot": {
"url": "https://s.yimg.com/iu/api/res/1.2/.0ocryeNkGmnFWlYOhT4hw--~C/YXBwaWQ9eXNwb3J0cztjaD0yMzM2O2NyPTE7Y3c9MTc5MDtkeD04NTc7ZHk9MDtmaT11bGNyb3A7aD02MDtxPTEwMDt3PTQ2/https://s.yimg.com/xe/i/us/sp/v/nfl_cutout/players_l/09272018/29238.png",
"size": "small"
},
"image_url": "https://s.yimg.com/iu/api/res/1.2/.0ocryeNkGmnFWlYOhT4hw--~C/YXBwaWQ9eXNwb3J0cztjaD0yMzM2O2NyPTE7Y3c9MTc5MDtkeD04NTc7ZHk9MDtmaT11bGNyb3A7aD02MDtxPTEwMDt3PTQ2/https://s.yimg.com/xe/i/us/sp/v/nfl_cutout/players_l/09272018/29238.png"
},
{
"is_undroppable": "0"
},
{
"position_type": "O"
},
[],
{
"eligible_positions": [
{
"position": "RB"
}
]
},
[],
[],
[]
]
]
},
"2": {
"player": [
[
{
"player_key": "390.p.30180"
},
{
"player_id": "30180"
},
{
"name": {
"full": "Alvin Kamara",
"first": "Alvin",
"last": "Kamara",
"ascii_first": "Alvin",
"ascii_last": "Kamara"
}
},
{
"editorial_player_key": "nfl.p.30180"
},
{
"editorial_team_key": "nfl.t.18"
},
{
"editorial_team_full_name": "New Orleans Saints"
},
{
"editorial_team_abbr": "NO"
},
{
"bye_weeks": {
"week": "9"
}
},
{
"uniform_number": "41"
},
{
"display_position": "RB"
},
{
"headshot": {
"url": "https://s.yimg.com/iu/api/res/1.2/loANJKjPdmUu1gM1jyKK1A--~C/YXBwaWQ9eXNwb3J0cztjaD0yMzM2O2NyPTE7Y3c9MTc5MDtkeD04NTc7ZHk9MDtmaT11bGNyb3A7aD02MDtxPTEwMDt3PTQ2/https://s.yimg.com/xe/i/us/sp/v/nfl_cutout/players_l/08252018/30180.png",
"size": "small"
},
"image_url": "https://s.yimg.com/iu/api/res/1.2/loANJKjPdmUu1gM1jyKK1A--~C/YXBwaWQ9eXNwb3J0cztjaD0yMzM2O2NyPTE7Y3c9MTc5MDtkeD04NTc7ZHk9MDtmaT11bGNyb3A7aD02MDtxPTEwMDt3PTQ2/https://s.yimg.com/xe/i/us/sp/v/nfl_cutout/players_l/08252018/30180.png"
},
{
"is_undroppable": "0"
},
{
"position_type": "O"
},
[],
{
"eligible_positions": [
{
"position": "RB"
}
]
},
[],
[],
[]
]
]
},
"count": 3
}
}
],
"time": "181.84494972229ms",
"copyright": "Data provided by Yahoo! and STATS, LLC",
"refresh_rate": "60"
}
}
有两件事让我失望。
game
是一个看起来很奇怪的数组,并且每个玩家面前都有一个索引,比如
0: { player: { //dah dah dah }
如果索引不存在,我可能会使用以下方法来计算它:
var jObject = JObject.Parse(await response.Content.ReadAsStringAsync());
if (jObject.ContainsKey("players"))
{
var yPs = jObject["players"].ToObject<YahooPlayerListJson>();
yPlayerList.AddRange(yPs.YPlayers);
if(yPs.Count < 25) { f = 5000; }
}
但索引给我带来了困难。如何解析这个 JSON?
解决方案
呃,这是一个非常糟糕的 JSON 格式。异构阵列使其特别难以使用。在我看来,这些数据是(严重)从 XML 转换而来的。如果是这样,直接使用 XML 可能更直接。无论如何,我们可以让它工作。这是我将采取的方法。
制作一些类来捕获您感兴趣的玩家数据:
public class Player { public string PlayerKey { get; set; } public string PlayerId { get; set; } public Name Name { get; set; } public string EditorialPlayerKey { get; set; } public string EditorialTeamKey { get; set; } public string EditorialTeamFullName { get; set; } public string EditorialTeamAbbr { get; set; } public Week ByeWeeks { get; set; } public string UniformNumber { get; set; } public string DisplayPosition { get; set; } public Photo Headshot { get; set; } public string ImageUrl { get; set; } public string IsUndroppable { get; set; } public string PositionType { get; set; } public Position[] EligiblePositions { get; set; } } public class Name { public string Full { get; set; } public string First { get; set; } public string Last { get; set; } } public class Photo { public string Url { get; set; } public string Size { get; set; } } public class Week { [JsonProperty("week")] public int Number { get; set; } } public class Position { [JsonProperty("position")] public string Name { get; set; } }
设置一个配置了
SnakeCaseNamingStrategy
. 这将处理snake_case
JSON 中的ProperCase
属性名称到 C# 类中的属性名称的转换。JsonSerializer serializer = new JsonSerializer { ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() } };
将 JSON 解析为
JObject
.string json = await response.Content.ReadAsStringAsync(); JObject root = JObject.Parse(json);
从那里使用LINQ-to-JSON查询来填充
Players
如下所示的列表。在这里,我使用
SelectTokens()
递归下降JsonPath表达式作为向下钻取player
对象的快捷方式。JSON 中的每个播放器实际上是一个包含混合内容数组的数组,其中内容由一些对象组成,每个对象包含一个不同的属性,以及一些无用的空数组。因此,我将内部数组过滤为仅包含真实数据的对象,然后将SelectMany()
它们的所有属性收集到一个 flatEnumerable<JProperty>
中,然后将其放入一个临时JObject
. 从那里我使用ToObject()
之前配置的序列化程序Player
从 中创建一个新实例JObject
并返回,Player
以便将其放入结果列表中。List<Player> players = root.SelectTokens("$..player") .Select(jt => { JObject tempObj = new JObject( jt.Children<JArray>() .First() .Children<JObject>() .SelectMany(jo => jo.Properties()) ); return tempObj.ToObject<Player>(serializer); }) .ToList();
如果您想
count
从 JSON 中获取 并将其与检索到的实际玩家数量进行比较,您可以这样做:int playerCount = (int)root.SelectToken("$..players.count"); if (players.Count != playerCount) throw new Exception("The number of players in the list does not match the player count!");
这是一个工作演示:https ://dotnetfiddle.net/8KYNNn
推荐阅读
- python - scikit-learn PCA方法中百分比值的解释
- sql - oracle查询找到关于jobrole的最高薪水
- scala - spark sql udf 强制转换返回值
- java - Eclipse 上单独文件中的 Java 文档
- javascript - 使用 jQuery 的 .clone() 保留复选框 onclick 功能
- html - 如何将自定义 HTML 添加到 wordpress 中的特定页面?
- spring-boot - Set active spring profile with bootWar
- python - Link 2 values of of different result
- floating-point - Precision of the quotient of two double precision numbers
- java - 使用 apache CXF 使用 equals/hashCode 方法从 WSDL 生成 POJO