Как я могу десериализовать результат JSON, где его Root является уникальным идентификатором в класс Object - PullRequest
0 голосов
/ 10 апреля 2020

В настоящее время я пытаюсь научиться работать с системами API, используя C#. net core 3 и Newtonsoft.

Следующий вызов Steam API - это то, что я использую для уточнения c деталей игры. Например, http://store.steampowered.com/api/appdetails?appids=72850

Это возвращает JSON аналогично этому (я упростил его для простоты)

{
    "72850": {
        "success": true,
        "data": {
            "type": "game",
            "name": "The Elder Scrolls V: Skyrim",
            "steam_appid": 72850,
            "required_age": 0,
            "is_free": false
        }
    }
}

Каждое возвращение имеет уникальный идентификатор как root в данном случае 72850, и я в растерянности, как сопоставить это с классом объектов, чтобы я мог обработать эти данные. Элемент «data» - это то, что меня действительно интересует, но я как новичок в растерянности.

Ответы [ 2 ]

0 голосов
/ 12 апреля 2020

Этот API индексирует свой ответ, используя внутренний Идентификатор запрошенного элемента.
Это распространенный сценарий, а также довольно эффективный метод организации объектов на основе индексатора, который затем можно использовать для хранения или получения этих данных. объекты, из базы данных, например.

Распространенный способ десериализации JSON объекта, проиндексированного таким образом, заключается в использовании словаря, где ключом является индексатор, а значением RootObject структуры класса (Модель), которая дополнительно описывает JSON свойства.

Некоторые примечания к текущему JSON:

  • API выглядит так, как будто он построен для представления JSON в документе HTML, поскольку внутренние строки отформатированы и готовы для представления на странице HTML. Это может быть менее полезно, когда используется в другом месте, а также может создать проблему при десериализации.
    Я добавил тривиальную очистку, заменив то, что наверняка может вызвать проблему:

    json = json.Replace(@"\/", "/").Replace(@"\t", "");
    
  • Я добавил еще несколько свойств и классов к представленным в вопросе: может быть полезно посмотреть, когда нужен атрибут JsonProperty, а когда - нет. Например: атрибут [JsonProperty("type")] добавляется к свойству public string GameType { get; set; }, поскольку Type - это ключевое слово, которое может быть неправильно истолковано, как Name et c.

  • Json.Net не чувствителен к регистру, поэтому свойство JSON background может быть присвоено свойству. Net public Uri Background { get; set; } без проблем.

Несколько веб-сайтов, предоставляющих бесплатный сервис для форматирования, проверки и преобразования JSON объекта в модель класса:

  • JsonFormatter - Форматирование, проверка
  • QuickType - Многоязычный генератор моделей классов

Загрузка JSON с использованием метода WebClient.DownloadString (), clean вверх по JSON и десериализации:

var steamUri = new Uri("https://store.steampowered.com/api/appdetails?appids=72850")
string json = new WebClient(steamUri).DownloadString();
json = json.Replace(@"\/", "/").Replace(@"\t", "");

var steamObj = JsonConvert.DeserializeObject<Dictionary<long, SteamApps.SteamAppDetails>>(json);

Структура класса :

public class SteamApps
{
    public class SteamAppDetails
    {
        public bool Success { get; set; }
        public Data Data { get; set; }
    }

    public class Data
    {
        [JsonProperty("type")]
        public string GameType { get; set; }

        [JsonProperty("name")]
        public string GameName { get; set; }

        [JsonProperty("steam_appid")]
        public long SteamAppid { get; set; }

        [JsonProperty("required_age")]
        public long RequiredAge { get; set; }

        [JsonProperty("is_free")]
        public bool IsFree { get; set; }

        [JsonProperty("short_description")]
        public string ShortDescription { get; set; }

        [JsonProperty("supported_languages")]
        public string Languages { get; set; }

        [JsonProperty("header_image")]
        public string HeaderImage { get; set; }

        public string WebSite { get; set; }

        [JsonProperty("price_overview")]
        public PriceOverview PriceOverview { get; set; }

        public Dictionary<string, bool> Platforms { get; set; }
        public List<Screenshot> Screenshots { get; set; }
        public Uri Background { get; set; }
        public List<Category> Categories { get; set; }
    }

    public class PriceOverview
    {
        public string Currency { get; set; }
        public long Initial { get; set; }
        public long Final { get; set; }

        [JsonProperty("discount_percent")]
        public decimal DiscountPercent { get; set; }

        [JsonProperty("initial_formatted")]
        public string InitialFormatted { get; set; }

        [JsonProperty("final_formatted")]
        public string FinalFormatted { get; set; }
    }

    public partial class Screenshot
    {
        [JsonProperty("id")]
        public long Id { get; set; }

        [JsonProperty("path_thumbnail")]
        public string PathThumbnail { get; set; }

        [JsonProperty("path_full")]
        public string PathFull { get; set; }
    }

    public partial class Category
    {
        [JsonProperty("id")]
        public long Id { get; set; }

        [JsonProperty("description")]
        public string Description { get; set; }
    }
}
0 голосов
/ 10 апреля 2020

Поскольку вам нужен только элемент «Данные» из json, использовать Newtonsoft довольно просто. Сначала создайте класс со всеми полями, которые содержит элемент Data, как показано ниже:

public class Data
{
    public string Type { get; set; }
    public string Name { get; set; }
    public long Steam_AppId { get; set; }
    public int Required_Age { get; set; }
    public bool Is_Free { get; set; }
}

Теперь, чтобы отобразить ответ json, который, как я предполагаю, в данный момент хранится в строке , вы должны десериализовать его, чтобы сопоставить его с вашим C# классом. И вы можете сделать это очень легко:

Редактировать: более элегантное решение, которое устраняет все неудобства манипуляции со строками

//You already have this but I created it in order to test
string jsonResult = "{ \"72850\": " +
    "{ \"success\": true, \"data\": " +
        "{ \"type\": \"game\", \"name\": \"The Elder Scrolls V: Skyrim\", " +
            "\"steam_appid\": 72850, \"required_age\": 0, \"is_free\": false } }";

//JObject is a class in Newtonsoft library for handling json objects
JObject jObject = JObject.Parse(jsonResult);

//Since you're sending a request to the api, either you already have the id 
//"72850" or can extract it easily from uri. This line gets data's value
//by 1st searching for key = "72850" and then within that a key = "data"
JToken dataToken = jObject["72850"]["data"];

Data data = dataToken.ToObject<Data>();

Ссылка: https://www.newtonsoft.com/json/help/html/SerializingJSONFragments.htm

Старое решение

//getting the value portion of data element/key
string jsonData = "{" + jsonResult.Substring(jsonResult.IndexOf("\"type"));
//removing the extra } from the end
jsonData = jsonData.TrimEnd('}');

//map the json string to a C# object
var dataObj = JsonConvert.DeserializeObject<Data>(jsonData);

Итак, теперь вы увидите значения json, сопоставленные с вашим объектом данных, который в данном случае является dataObj. Не стесняйтесь задавать вопросы, если что-то не понятно. Ура!

...