有条件地将不同的 json 属性 反序列化为同一模型 属性

Deserialize different json property to same model property conditionally

假设我有以下 json。

{
   "allitemscount":2,
   "allitems":[
        {"itemid":"1","itemname":"one"}, 
        {"itemid":"2","itemname":"two"}],
   "customitems":[
       {"itemid":"3","itemname":"three"}, 
       {"itemid":"4","itemname":"four"}]
}

反序列化这个 json 时,它应该转到下面的 C# 模型。

public class response
{
  public int allitemscount;
  public List<item> items;
}

public class item
{
   public string itemid;
   public string itemname;
}

问题: 如何根据条件在 allitemscustomitems 之间切换?例如,如果 useAllitems 为真,allitems 来自 json 要填写的项目,如果 useCustomItems 为真, customitems 要填写的项目属性。请帮助如何做到这一点。

public List<item> items 上使用 JsonProperty 允许在 allitems 之间切换,但是有没有一种方法可以根据上述条件进行反序列化。

您可以通过如下更改 response class 来反序列化上述 json,

public class response{
      public int allitemscount;
      public List<item> allitems;
      public List<item> customitems;    
}

然后使用下面的代码,

var jsonData = "{\"allitemscount\":2,   \"allitems\":[{\"itemid\":\"1\",\"itemname\":\"one\"}, {\"itemid\":\"2\",\"itemname\":\"two\"}],\"customitems\":[{\"itemid\":\"3\",\"itemname\":\"three\"},{\"itemid\":\"4\",\"itemname\":\"four\"}]}";

var data = JsonConvert.DeserializeObject<response>(jsonData);
foreach(var str in data.allitems) {
          Console.WriteLine(str.itemid +'-'+str.itemname);
}
foreach(var str in data.customitems) {
          Console.WriteLine(str.itemid +'-'+str.itemname);
}

我是通过编写我们自己的继承自 JsonConverter 的 ItemConverter 实现的,

我在尝试中使用的示例模型 json:

{
  "allitemscount": 2,
  "UseCustomItems": true,
  "allitems": [
    {
      "itemid": "1",
      "itemname": "one"
    },
    {
      "itemid": "2",
      "itemname": "two"
    }
  ],
  "customitems": [
    {
      "itemid": "3",
      "itemname": "three"
    },
    {
      "itemid": "4",
      "itemname": "four"
    }
  ]
}

控制台应用程序的主要方法:

static void Main(string[] args)
{
    using (StreamReader r = new StreamReader(@"\model.json")) // json path
    {
        string json = r.ReadToEnd();

        var deserializedJson = JsonConvert.DeserializeObject<Result>(json, new ItemConverter());
    }
}

型号:

public class Result // main object
{
    [JsonProperty("allitemscount")]
    public long Allitemscount { get; set; }

    public bool UseCustomItems { get; set; }
}

public class ResultA : Result // CustomItems Model
{
    [JsonProperty("customitems")]
    private List<Item> Items { get; set; }
}

public class ResultB : Result // AllItems Model
{
    [JsonProperty("allitems")]
    private List<Item> Items { get; set; }
}

public class Item
{
    [JsonProperty("itemid")]
    public string Itemid { get; set; }

    [JsonProperty("itemname")]
    public string Itemname { get; set; }
}

以及我们在反序列化到对象时使用的 ItemConverter:

internal class ItemConverter : JsonConverter
{
    private Type currentType;

    public override bool CanConvert(Type objectType)
    {
        return typeof(Item).IsAssignableFrom(objectType) || objectType == typeof(Result);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject item = JObject.Load(reader);
        if (item["UseCustomItems"] != null)
        {
            // save the type for later.
            switch (item["UseCustomItems"].Value<bool>())
            {
                case true:
                    currentType = typeof(ResultA);
                    return item.ToObject<ResultA>(); // return result as customitems result
                case false:
                    currentType = typeof(ResultB);
                    return item.ToObject<ResultB>(); // return result as allitems result
            }
            return item.ToObject<Result>();
        }

        // use the last type you read to serialise.
        return item.ToObject(currentType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

结果应该如下图所示

希望这个解决方案对您有所帮助