首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >反序列化雅虎!幻想API播放器JSON

反序列化雅虎!幻想API播放器JSON
EN

Stack Overflow用户
提问于 2014-07-21 18:35:43
回答 1查看 871关注 0票数 1

我试图反序列化雅虎返回的JSON!幻想API,使用此资源:

http://fantasysports.yahooapis.com/fantasy/v2/game/nfl/players;start=0;count=1?format=json

RestSharp在试图反序列化Player对象(它是数组的数组)时抛出以下异常:

无法将“RestSharp.JsonArray”类型的对象强制转换为“RestSharp.JsonArray System.Object”类型

如果我将Player属性排除在PlayerRoot类之外,反序列化是成功的(但当然缺少大多数有用的信息)。

我使用的是手工编码的对象模型;Visual中的Paste Special-->Paste JSON as Classes操作不适用于下面所示的JSON,但它看起来确实是有效的JSON。

我的对象模型有什么问题吗?我的假设是,关于player元素(嵌套数组)的某些内容正在炸毁RestSharp JSON反序列化器。

客户端代码

代码语言:javascript
运行
复制
public void GetPlayers()
{
    int start = 0;
    int count = 1;
    var request =
        new RestRequest("game/{gameType}/players;start={start};count={count}",
                        Method.GET);
    request.AddUrlSegment("gameType", _gameType);
    request.AddUrlSegment("start", start.ToString());
    request.AddUrlSegment("count", count.ToString());

    // This extension adds "?format=json" to the query string
    request.AddJsonParam();

    var response = _client.Execute<FantasyModel>(request);
    var data = (FantasyModel)response.Data;
}

模型

代码语言:javascript
运行
复制
public class FantasyModel
{
    public FantasyContent FantasyContent { get; set; }
}

public class FantasyContent
{
    [DeserializeAs(Name = "xml:lang")]
    public string Language { get; set; }

    [DeserializeAs(Name = "yahoo:uri")]
    public string YahooUri { get; set; }

    public string Time { get; set; }

    public string Copyright { get; set; }

    public string RefreshRate { get; set; }

    public List<Game> Game { get; set; }
}

public class Game
{
    public string GameKey { get; set; }

    public string GameId { get; set; }

    public string Name { get; set; }

    public string Code { get; set; }

    public string Type { get; set; }

    public string Url { get; set; }

    public string Season { get; set; }

    public StatCategories StatCategories { get; set; }

    public Players Players { get; set; }
}

public class Players
{
    [DeserializeAs(Name = "0")]
    public PlayerRoot PlayerRoot { get; set; }

    public int Count { get; set; }
}

public class PlayerRoot
{
    public PlayerRoot()
    {
        Player = new List<List<Player>>();
    }

    public List<List<Player>> Player { get; set; }
}

public class Player
{
    public Player()
    {
        Name = new PlayerName();
        ByeWeeks = new ByeWeeks();
        Headshot = new Headshot();
        EligiblePositions = new List<EligiblePosition>();
    }

    public string PlayerKey { get; set; }

    public string PlayerId { get; set; }

    public PlayerName Name { get; set; }

    public string EditorialPlayerKey { get; set; }

    public string EditorialTeamKey { get; set; }

    public string EditorialTeamFullName { get; set; }

    public string EditorialTeamAbbr { get; set; }

    public ByeWeeks ByeWeeks { get; set; }

    public string UniformNumber { get; set; }

    public string DisplayPosition { get; set; }

    public Headshot Headshot { get; set; }

    public string ImageUrl { get; set; }

    public string IsUndroppable { get; set; }

    public string PositionType { get; set; }

    public List<EligiblePosition> EligiblePositions { get; set; }
}

public class PlayerName
{
    public string Full { get; set; }

    public string First { get; set; }

    public string Last { get; set; }

    public string AsciiFirst { get; set; }

    public string AsciiLast { get; set; }
}

public class ByeWeeks
{
    public string Week { get; set; }
}

public class Headshot
{
    public string Url { get; set; }

    public string Size { get; set; }
}

public class EligiblePosition
{
    public string Position { get; set; }
}

JSON

代码语言:javascript
运行
复制
{
    "fantasy_content": {
        "xml:lang": "en-US",
        "yahoo:uri": "\/fantasy\/v2\/game\/nfl\/players;count=1;start=0",
        "game": [
            {
                "game_key": "331",
                "game_id": "331",
                "name": "Football",
                "code": "nfl",
                "type": "full",
                "url": "http:\/\/football.fantasysports.yahoo.com\/f1",
                "season": "2014"
            },
            {
                "players": {
                    "0": {
                        "player": [
                            [
                                {
                                    "player_key": "331.p.8850"
                                },
                                {
                                    "player_id": "8850"
                                },
                                {
                                    "name": {
                                        "full": "Jamaal Charles",
                                        "first": "Jamaal",
                                        "last": "Charles",
                                        "ascii_first": "Jamaal",
                                        "ascii_last": "Charles"
                                    }
                                },
                                {
                                    "editorial_player_key": "nfl.p.8850"
                                },
                                {
                                    "editorial_team_key": "nfl.t.12"
                                },
                                {
                                    "editorial_team_full_name": "Kansas City Chiefs"
                                },
                                {
                                    "editorial_team_abbr": "KC"
                                },
                                {
                                    "bye_weeks": {
                                        "week": "6"
                                    }
                                },
                                {
                                    "uniform_number": "25"
                                },
                                {
                                    "display_position": "RB"
                                },
                                {
                                    "headshot": {
                                        "url": "http:\/\/l.yimg.com\/iu\/api\/res\/1.2\/084uD0cG9qCYdPSjJLX9.A--\/YXBwaWQ9eXZpZGVvO2NoPTg2MDtjcj0xO2N3PTY1OTtkeD0xO2R5PTE7Zmk9dWxjcm9wO2g9NjA7cT0xMDA7dz00Ng--\/http:\/\/l.yimg.com\/j\/assets\/i\/us\/sp\/v\/nfl\/players_l\/20120913\/8850.jpg",
                                        "size": "small"
                                    },
                                    "image_url": "http:\/\/l.yimg.com\/iu\/api\/res\/1.2\/084uD0cG9qCYdPSjJLX9.A--\/YXBwaWQ9eXZpZGVvO2NoPTg2MDtjcj0xO2N3PTY1OTtkeD0xO2R5PTE7Zmk9dWxjcm9wO2g9NjA7cT0xMDA7dz00Ng--\/http:\/\/l.yimg.com\/j\/assets\/i\/us\/sp\/v\/nfl\/players_l\/20120913\/8850.jpg"
                                },
                                {
                                    "is_undroppable": "0"
                                },
                                {
                                    "position_type": "O"
                                },
                                {
                                    "eligible_positions": [
                                        {
                                            "position": "RB"
                                        }
                                    ]
                                },
                                [ ],
                                [ ]
                            ]
                        ]
                    },
                    "count": 1
                }
            }
        ],
        "time": "215.82293510437ms",
        "copyright": "Data provided by Yahoo! and STATS, LLC",
        "refresh_rate": "60"
    }
}

注意:上面JSON中的"0"对象将被重复使用n times,game/{gameType}/players;start={start};count={count}n = {count}。生成的JSON如下所示:

代码语言:javascript
运行
复制
{
    "fantasy_content": {
        ...
                "players": {
                    "0": { }
                    "1": { }
                    "2": { }
                    ...

为了这个问题的目的,我只带回一个对象({count} = 1)。

编辑

经过进一步的检查,player对象应该是List<List<object>>object[][],因为播放器的每个属性都是数组中的自己的元素。

我仍然不知道如何使用RestSharp反序列化器来反序列化这个东西,但是我能够通过使用Json.NET获得我所需要的大部分内容。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-22 14:02:00

我无法使用RestSharp内置的反序列化器来反序列化这个JSON。我认为雅虎在这里返回了一些相当奇怪的JSON ( players对象本质上是一个对象列表的字典),而这种陌生使得自动反序列化变得困难。

我用Json.NETCustomCreationConverter解决了这个问题。我并不特别喜欢这个解决方案,而且我认为有更好的方法来完成它,但是在一个紧迫的截止日期,这就是我想出的(错误处理/日志记录/为了简洁而删除等):

新客户端代码

代码语言:javascript
运行
复制
var request =
    new RestRequest("game/{gameType}/players;start={start};count={count}", Method.GET);
request.AddUrlSegment("gameType", _gameType);
request.AddUrlSegment("start", start.ToString());
request.AddUrlSegment("count", count.ToString());
request.AddJsonParam();

var response = _client.Execute(request);
var json = JObject.Parse(response.Content);
var playersJson = json["fantasy_content"]["game"][1]["players"];

// Remove the count element
playersJson.Last.Remove();

var players = JsonConvert.DeserializeObject<Dictionary<string, Player>>(
    playersJson.ToString(), new JsonPlayerConverter());

新玩家类

代码语言:javascript
运行
复制
public class Player
{
    public Player()
    {
        Name = new PlayerName();
        ByeWeeks = new ByeWeeks();
        Headshot = new Headshot();
        EligiblePositions = new List<EligiblePosition>();
    }

    [JsonProperty(PropertyName = "player_key")]
    public string PlayerKey { get; set; }

    [JsonProperty(PropertyName = "player_id")]
    public string PlayerId { get; set; }

    [JsonProperty(PropertyName = "name")]
    public PlayerName Name { get; set; }

    [JsonProperty(PropertyName = "editorial_player_key")]
    public string EditorialPlayerKey { get; set; }

    [JsonProperty(PropertyName = "editorial_team_key")]
    public string EditorialTeamKey { get; set; }

    [JsonProperty(PropertyName = "editorial_team_full_name")]
    public string EditorialTeamFullName { get; set; }

    [JsonProperty(PropertyName = "editorial_team_abbr")]
    public string EditorialTeamAbbr { get; set; }

    [JsonProperty(PropertyName = "bye_weeks")]
    public ByeWeeks ByeWeeks { get; set; }

    [JsonProperty(PropertyName = "uniform_number")]
    public string UniformNumber { get; set; }

    [JsonProperty(PropertyName = "display_position")]
    public string DisplayPosition { get; set; }

    [JsonProperty(PropertyName = "headshot")]
    public Headshot Headshot { get; set; }

    [JsonProperty(PropertyName = "image_url")]
    public string ImageUrl { get; set; }

    [JsonProperty(PropertyName = "is_undroppable")]
    public string IsUndroppable { get; set; }

    [JsonProperty(PropertyName = "position_type")]
    public string PositionType { get; set; }

    [JsonProperty(PropertyName = "eligible_positions")]
    public List<EligiblePosition> EligiblePositions { get; set; }
}

CustomCreationConverter

代码语言:javascript
运行
复制
public class JsonPlayerConverter : CustomCreationConverter<Player>
{
    public override Player Create(Type objectType)
    {
        throw new NotImplementedException();
    }

    public Player Create(Type objectType, JObject obj)
    {
        var array = obj["player"][0];
        var content = array.Children<JObject>();

        var player = new Player();
        foreach (var prop in player.GetType().GetProperties())
        {
            var attr = prop.GetCustomAttributes(typeof(JsonPropertyAttribute), false).FirstOrDefault();
            var propName = ((JsonPropertyAttribute)attr).PropertyName;
            var jsonElement = content.FirstOrDefault(c => c.Properties()
                                    .Any(p => p.Name == propName));
            var value = jsonElement.GetValue(propName);
            var type = prop.PropertyType;

            if (type == typeof(string))
            {
                prop.SetValue(player, (string)value, null);
            }
            else if (type  == typeof(PlayerName))
            {
                var playerName = JsonConvert.DeserializeObject<PlayerName>(value.ToString());
                prop.SetValue(player, (PlayerName)playerName, null);
            }
            else if (type == typeof(Headshot))
            {
                var headshot = JsonConvert.DeserializeObject<Headshot>(value.ToString());
                prop.SetValue(player, headshot, null);
            }
            else if (type == typeof(ByeWeeks))
            {
                var byeWeeks = JsonConvert.DeserializeObject<ByeWeeks>(value.ToString());
                prop.SetValue(player, byeWeeks, null);
            }
            else if (type == typeof(List<EligiblePosition>))
            {
                var eligiblePositions = JsonConvert.DeserializeObject<List<EligiblePosition>>(value.ToString());
                prop.SetValue(player, eligiblePositions, null);
            }
        }
        return player;
    }

    public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
    {
        var obj = JObject.Load(reader);
        var target = Create(objectType, obj);
        serializer.Populate(obj.CreateReader(), target);

        return target;
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24872285

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档