动态将JSON反序列化为基于内容的派生类型? [英] Deserialize JSON dynamically to derived types based on content?

查看:52
本文介绍了动态将JSON反序列化为基于内容的派生类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我作为辅助项目编写的小图书馆中,我使用RestSharp从Web API获取Json.将反序列化为模型类可用于简单类型,但在某些端点在请求时生成的类型未知(或不清楚).

In my little library I'm writing as a side project, I'm using RestSharp to get Json from a web API. The deserialization into model classes works fine for simple types, but there are endpoints where the resulting type is unknown (or unclear) at request time.

特别是其GuildWars2 API v1,其中一个示例是商品数据.当然,每个项目都有一些基本属性,并根据查询的项目设置其他值.例如,武器具有一些修改器,依此类推.

Specifically its the GuildWars2 API v1 and one example would be item data. There are of course basic properties every item has and additional values are set depending on the queried item. For example a weapon has some modifiers and so on.

我的想法是为所有基本属性创建一个抽象的Item类,并从该类派生所有添加所需属性的项目的所有现有子类型.我的问题是,如何确定要反序列化到的子类.我已经读过各种有关在Json字符串中添加限定类型名称的方法,但是由于我仅从API获取数据,因此无法影响响应.

My idea was to create an abstract Item class for all basic properties and derive from that class for all the existing subtypes of items adding needed properties. My problem is, how to decide which subclass to deserialize into. I already read about various methods involving adding a qualified type name to the Json string but since I only get the data from an API, I cannot influence the response im getting.

理想情况下,我总是希望通过反序列化器通过Json字符串中包含的给定属性来确定实际类型,从而将反序列化为基类Item.还是有更好的方法来解决这个问题?

I would ideally always want to deserialize into the base class Item with the deserializer deciding the actual type via the given properties contained in the Json string.. Is this a possibility? Or is there a better way to solve this problem?

预先感谢

这是武器的Json示例:

This is an example Json of a weapon:

{
  "item_id": "30704",
  "name": "Twilight",
  "description": "",
  "type": "Weapon",
  "level": "80",
  "rarity": "Legendary",
  "vendor_value": "100000",
  "icon_file_id": "456031",
  "icon_file_signature": "CE3AF0B7B9BB6244726779F5B6A930541BA6C15F",
  "game_types": ["Activity", "Dungeon", "Pve", "Wvw"],
  "flags": ["HideSuffix", "NoSell", "SoulBindOnUse"],
  "restrictions": [],
  "weapon": {
    "type": "Greatsword",
    "damage_type": "Physical",
    "min_power": "995",
    "max_power": "1100",
    "defense": "0",
    "infusion_slots": [],
    "infix_upgrade": {
      "attributes": [
        {
          "attribute": "Power",
          "modifier": "179"
        },
        {
          "attribute": "Power",
          "modifier": "179"
        }
      ]
     },
     "suffix_item_id": "24599"
   }
}

这将是一件盔甲:

{
  "item_id":"500",
  "name":"Carrion Conjurer Chest of Dwayna", 
  "description":"",
  "type":"Armor",
  "level":"68",
  "rarity":"Rare",
  "vendor_value":"257",
  "icon_file_id":"61023",
  "icon_file_signature":"76CD08463A05730071D400254141B50E570662D3",
  "game_types":["Activity", "Dungeon", "Pve", "Wvw"],
  "flags":["SoulBindOnUse"],
  "restrictions":[],
  "armor": {
    "type":"Coat",
    "weight_class":"Light",
    "defense":"221",
    "infusion_slots":[],
    "infix_upgrade": {
      "attributes": [
        {
          "attribute":"ConditionDamage","modifier":"70"
        },
        {
          "attribute":"Power","modifier":"50"
        }
      ]
    },
    "suffix_item_id":"24767"
  }
}

我想基于属性"Type"的内容反序列化,但我不知道这将如何工作=/

I'd like to deserialize based on the content of the property "Type", but I cannot figure out, how that would work =/

推荐答案

您可以使用JObject解析JSON数据,然后将其用作关联数组.

You can parse your JSON data with JObject, which then can be used as an associative array.

string json = @"{
  "item_id": "30704",
  "name": "Twilight",
  "description": "",
  "type": "Weapon",
  ...
}";

JObject o = JObject.Parse(json);

Item item = null;
switch (o["type"])
{
    case "Weapon":
      item = JsonConvert.DeserializeObject<Weapon>(json);
    break;
    case "Armor":
      item = JsonConvert.DeserializeObject<Armor>(json);
    break;
    default:
      // throw error?
}

然后您将拥有一个这样的基类:

and then you'd have a base class as such:

public class Item
{
  public string item_id { get; set; }
  public string name { get; set; }
  public string description { get; set; }
  public string type { get; set; }
  ...
  // List all common properties here
  public Item() { } 
  // It's important to have the public default constructor implemented 
  // if you intend on overloading it for your own purpose later
}

您的武器课可能就是这样:

And your Weapon class could be as such:

public class Weapon : Item // Weapon extends Item
{
  public WeaponDetails weapon { get; set; }
  public Weapon() { }
}

和武器详细信息:

public class WeaponDetails
{
  public string type { get; set; }
  public string damage_type { get; set; }
  public int min_power { get; set; }
  public int max_power { get; set; }
  ...
  public WeaponDetails() { }
}

这篇关于动态将JSON反序列化为基于内容的派生类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆