簡體   English   中英

將 JSON 轉換為具有泛型類型的列表

[英]Convert JSON to list with generic types

我得到了一個 JSON 響應,如:

{
  "items": [
    {
      "document": {
        "id": "123",
        "title": "title2",
        "description": "Description1",
        "type": "Typ1"
      }
    },
    {
      "document": {
        "id": "456",
        "title": "title2",
        "description": "desctiption2",
        "type": "Type2",
        "Type2Property": "Type2Property"
      }
    }
  ]
}

正如您在上面看到的,我有兩個具有不同屬性的值(例如)。 在我的代碼中,我有兩個類。

public class Type1
{
    public string Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public string Type { get; set; }
}

public class Type2
{
    public string Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public string Type { get; set; }
    public string Type2Property {get; set;}
}

問題:如何創建一個結合 Type1 和 Type2 的通用列表。 將來,我可以擁有更多的 TypeX(具有不同的屬性)。 所以,我想將 JSON 解析為通用列表。

更新:我可以通過 JSON 中的 Type 屬性過濾 json。

解決此問題的一種方法是創建自定義JsonConverter並覆蓋其ReadJson方法。

我引入了幾個幫助類來解析整個示例 json:

public class TopLevel
{
    public MidLevel[] Items { get; set; }
}

public class MidLevel
{
    public IDocument Document { get; set; }

}

[JsonConverter(typeof(DocumentTypeConverter))]
public interface IDocument
{
}
  • 我創建了一個IDocument標記界面。 如果您願意,可以使用abstract class
  • 我用JsonConverterAttribute裝飾了界面,並在那里指定了自定義轉換器。
  • 我改變了Type1Type2類來實現這個接口:
public class Type1 : IDocument
{
    ...
    public string Type { get; set; }
}

public class Type2 : IDocument
{
    ...
    public string Type { get; set; }
    public string Type2Property { get; set; }
}

DocumentTypeConverter實現如下所示:
(顯然你可以使更多的類型安全)

public class DocumentTypeConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
        => throw new NotImplementedException();

    public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
    {
        var jObject = JObject.Load(reader);
        switch (jObject["type"].Value<string>())
        {
            case "Typ1":
                {
                    var obj = new Type1();
                    serializer.Populate(jObject.CreateReader(), obj);
                    return obj;
                }
            case "Type2":
                {
                    var obj = new Type2();
                    serializer.Populate(jObject.CreateReader(), obj);
                    return obj;
                }
            default:
                throw new Exception();
        }
    }

    public override bool CanConvert(Type objectType) 
        => objectType == typeof(IDocument);
}
  • CanConvert告訴我們這個轉換可以用於IDocument s。
  • ReadJson 根據“類型”字段分支其邏輯。
  • 實際轉換使用Populate而不是JsonCovert.Deserialize完成,以避免無限遞歸

最后,用法就是這么簡單:

static void Main(string[] args)
{
    var sampleJson = File.ReadAllText("sample.json");
    var sample = JsonConvert.DeserializeObject<TopLevel>(sampleJson);
    Console.ReadLine();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM