根据内容动态地将JSON反序列化为派生类型?

MrF*_*oya 7 c# json restsharp deserialization

在我的小库中,我正在编写一个侧面项目,我正在使用RestSharp从Web API获取Json.对模型类的反序列化对于简单类型可以正常工作,但是在请求时有结果类型未知(或不清楚)的端点.

特别是它的GuildWars2 API v1和一个例子是项目数据.当然,每个项目都有基本属性,并根据查询的项目设置其他值.例如,武器有一些修饰符等等.

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

理想情况下,我总是希望反序列化到基类Item中,反序列化器通过Json字符串中包含的给定属性来决定实际类型.这是否可能?或者有更好的方法来解决这个问题吗?

提前致谢

编辑:这是武器的Json示例:

{
  "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"
   }
}
Run Code Online (Sandbox Code Playgroud)

这将是一件盔甲:

{
  "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"
  }
}
Run Code Online (Sandbox Code Playgroud)

我想基于属性"类型"的内容反序列化,但我无法弄清楚,这将如何工作= /

小智 5

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

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?
}
Run Code Online (Sandbox Code Playgroud)

然后你会有一个基类:

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
}
Run Code Online (Sandbox Code Playgroud)

而你的武器类可以是这样的:

public class Weapon : Item // Weapon extends Item
{
  public WeaponDetails weapon { get; set; }
  public Weapon() { }
}
Run Code Online (Sandbox Code Playgroud)

和武器细节:

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() { }
}
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢您的回答!这正是我所想象的。我刚刚还有一个问题。这段代码不会解析JSON两次吗?首先作为 JObject,然后作为适当的类型?这不是一个大问题,但如果我需要解析大量 JSON,这可能是一个问题。 (2认同)