【问题标题】:Calling an Api multiple times C#多次调用 Api C#
【发布时间】:2021-01-27 05:32:50
【问题描述】:

我正在尝试使用 rawg api 并从他们的 api 获取游戏,我创建了游戏实体类来解析数据

//game entity
public class Game
    {
        public int Id { get; set; }
        public string Slug { get; set; }
        public string Name { get; set; }
        public string Released { get; set; }
        public string Background_Image { get; set; }
        public int Rating { get; set; }
        public int Playtime { get; set; }
    }

现在我需要从 api 获取游戏,我做了这个方法

public static async Task<List<Game>> ApiRawgGamesRequest()
        {
            var gamesList = new List<Game>();

            for (int i = 1; i < 250; i++)
            {
                using (var msg = new HttpRequestMessage(HttpMethod.Get, new Uri($"https://api.rawg.io/api/games?page_size=40&page={i}")))
                using (var response = await _client.SendAsync(msg))
                {
                    response.EnsureSuccessStatusCode();
                    var gamesResponse = await response.Content.ReadAsAsync<Game[]>();
                    gamesList.AddRange(gamesResponse);
                }
            }

            return gamesList;
        }

我试图不一次添加所有游戏,所以我使用 for 循环不断地将游戏添加到列表中,以潜在地减轻压力。 但我得到一个错误

// error
Unhandled exception. System.AggregateException: One or more errors occurred. (Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'Domain.Game[]' because the t
ype requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a
collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'count', line 1, position 9.)

来自 rawg api 的响应看起来像这样——结果部分是我试图收集的游戏数据

// api response
{
"count": 454988,
"next": "https://api.rawg.io/api/games?page=2&page_size=40",
"previous": null,
"results": [
{
"id": 3498,
"slug": "grand-theft-auto-v",
"name": "Grand Theft Auto V",
"released": "2013-09-17",
"tba": false,
"background_image": "https://media.rawg.io/media/games/84d/84da2ac3fdfc6507807a1808595afb12.jpg",
"rating": 4.48,
},
{
"id": 4200,
"slug": "portal-2",
"name": "Portal 2",
"released": "2011-04-18",
"tba": false,
"background_image": "https://media.rawg.io/media/games/328/3283617cb7d75d67257fc58339188742.jpg",
"rating": 4.62
}
]
}

有没有更好的方法来做到这一点?

【问题讨论】:

标签: c# asp.net-core asp.net-web-api .net-core


【解决方案1】:

您的异常是由错误的 JSON 解析对象引起的。
在您调用的代码中:

var gamesResponse = await response.Content.ReadAsAsync<Game[]>();

但响应是对象(来自您的示例 JSON):

public class GameResponse
    {
        public int Count { get; set; }
        public string Next{ get; set; }
        public string Previous { get; set; }
        public IEnumerable<Game> Results { get; set; }
    }

如果你把它改成:

var gamesResponse = await response.Content.ReadAsAsync<GameResponse>();

您将成功解析响应并通过以下方式访问游戏:

gamesResponse.Results

【讨论】:

  • 我怀疑是这个,你证明是对的。非常感谢!
【解决方案2】:

因此,您尝试仅反序列化 json 的“结果”部分,您必须使用响应 json 中的所有项目构建一个类。

// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse); 
    public class Result    {
        public int id { get; set; } 
        public string slug { get; set; } 
        public string name { get; set; } 
        public string released { get; set; } 
        public bool tba { get; set; } 
        public string background_image { get; set; } 
        public double rating { get; set; } 
    }

    public class Root    {
        public int count { get; set; } 
        public string next { get; set; } 
        public object previous { get; set; } 
        public List<Result> results { get; set; } 
    }

您总是可以在线使用某种 Json> 类生成器,将此用于此 anwser:https://json2csharp.com/

【讨论】:

    【解决方案3】:

    有几个很好的答案可以解决结构不正确的问题。我在这里添加的唯一一个好的做法是为了更好地控制你的变量名是注释。请注意,DataContract 和 DataMember 是框架的一部分,但可以很好地与 Json.Net 一起使用,即使 Json.Net 带有它们自己的一组注释。

        [DataContract]
        public class Payload
        {
            [DataMember(Name = "count")]
            public int Count { get; set; }
    
            [DataMember(Name = "next")]
            public string Next { get; set; }
    
            [DataMember(Name = "previous")]
            public string Previous { get; set; }
    
            [DataMember(Name = "results")]
            public List<GameData> Results { get; set; }
        }
    
        [DataContract]
        public class GameData
        {
            [DataMember(Name = "id")]
            public long Id { get; set; }
    
            [DataMember(Name = "slug")]
            public string Slug { get; set; }
    
            [DataMember(Name = "name")]
            public string Name { get; set; }
    
            [DataMember(Name = "rating")]
            public float Rating { get; set; }
    
            [DataMember(Name = "rating_top")]
            public float Rating_top { get; set; }
        }
    
        public static async Task<IEnumerable<Payload>> GetGameDatasAsync(int page = 1, int pageSize = 40, bool followNext = false, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
    
            string next = $"https://api.rawg.io/api/games?page_size={pageSize}&page={page}";
            var results = new List<Payload>();
    
            using (var client = new HttpClient())
                do
                {
                    var result = await client.GetAsync(next, cancellationToken);
    
                    next = string.Empty;
    
                    if (result.IsSuccessStatusCode)
                    {
                        var json = await result.Content.ReadAsStringAsync();
    
                        if (!string.IsNullOrWhiteSpace(json))
                        {
                            var payload = JsonConvert.DeserializeObject<Payload>(json);
    
                            next = payload.Next;
    
                            results.Add(payload);
                        }
                    }
    
                } while (!string.IsNullOrWhiteSpace(next) && followNext);
    
            return results;
        }
    

    【讨论】:

      猜你喜欢
      • 2022-01-01
      • 2022-01-14
      • 1970-01-01
      • 2020-10-05
      • 2018-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多