根据元素的内容反序列化 JSON 到不同的元素

De-Serialize JSON to different elements based on content of element

我正在尝试将 JSON 文件解析为不同的项目,该文件包含具有以下示例内容的项目:

{
    "PM00000001": { "description": "Manufacturing","cost": -1,"group":"Manufacturing","WeldAngleDegrees": 60},
    "PM00000010": {"description": "Plate Roll","cost": 90,"unit": "hr","group": "Roll","setup": 0.5,"speed": 0.4},
    "PM00000011": {"description": "Weld SAW","cost": 90,"unit": "hr","group": "Weld","width": 0.5,"thickness": 50}
}

每个项目都有描述、成本和组别。其余属性取决于组。在上面的示例中,制造有 "WeldAngleDegrees",轧制有 setupspeed,焊接有 widththickness

我正在尝试使用 JSON.NET 来解析这个文件。

现在我正在这样做:

string text = System.IO.File.ReadAllText(ofd.FileName);
Dictionary<string, Item> deserializedProduct = JsonConvert.DeserializeObject<Dictionary<string, Item>>(text, new ItemConverter());

public class Item
{
    public string description { get; set; }
    public double cost { get; set; }
    public string group { get; set; }
}

public class ManufacturingItem : Item
{
    public string WeldAngleDegrees { get; set; }
}

public class ItemConverter : CustomCreationConverter<Item>
{
    public override Item Create(Type objectType)
    {
        return new ManufacturingItem();
    }
}

ItemConverter 中有没有办法找出该项目属于哪个 "group" 以创建正确的项目类型?

有更简单的方法吗?

只需将你的 json 反序列化为字典,并根据组的值解释值。

var dict = JsonConvert.DeserializeObject<Dictionary<string, MyItem>>(json);

public class MyItem
{
    public string Description { get; set; }
    public int Cost { get; set; }
    public string Group { get; set; }
    public int WeldAngleDegrees { get; set; }
    public string Unit { get; set; }
    public double Width { get; set; }
    public int Thickness { get; set; }   
    public double Speed { get; set; }
    public double Setup { get; set; } 

}

不是从 CustomCreationConverter<T> 派生你的 ItemConverter,而是从 JsonConverter 派生它;那么您将可以通过 reader 访问 JSON。您可以将对象数据加载到 JObject,然后检查 group 属性 以确定要创建哪个 class。代码可能如下所示:

public class ItemConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Item);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        string group = (string)jo["group"];
        if (group == "Manufacturing")
        {
            return jo.ToObject<ManufacturingItem>();
        }
        else if (group == "Roll")
        {
            return jo.ToObject<RollItem>();
        }
        else if (group == "Weld")
        {
            return jo.ToObject<WeldItem>();
        }
        throw new JsonSerializationException("Unexpected item (group) type");
    }

    public override bool CanWrite
    {
        get { return false; }
    }

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

Fiddle: https://dotnetfiddle.net/8ZIubu