【问题标题】:JSON infer class type based on Dictionary key基于字典键的 JSON 推断类类型
【发布时间】:2016-08-29 21:42:13
【问题描述】:

我想反序列化 Dictionary<string, AbstractDataObject>。 AbstractDataObject 是 SomeClass1 和 SomeClass2 继承自的抽象类。字典的键值(一个字符串)是类的名称:

{
  "StoredData": {
    "SomeClass1": {
      "Foo": "Test"
    },
    "SomeClass2": {
      "Bar": 123
    }
  }
}

类如下所示(简化):

public class Data
{
    public Dictionary<string, AbstractDataObject> StoredData { get; set; }
}

public abstract class AbstractDataObject
{
}

public class SomeClass1 : AbstractDataObject 
{
    public string Foo { get; set; }
}

public class SomeClass2 : AbstractDataObject
{
    public int Bar { get; set; }
}

如何告诉 Json.NET 根据 Dictionary 键推断类类型?我环顾四周,但不确定从哪里开始实现此功能

【问题讨论】:

  • 使用类型名称是危险的,因为它违背了序列化的典型目的,即允许完全解耦的客户端/服务器。有没有一种方法可以设计成有明确的合同?
  • @SilasReinagel 你说的显式契约是什么意思?
  • 例如,在您的客户端代码中使用具体的数据对象,用于特定的远程调用。
  • @SilasReinagel 哦,那将需要完全重写我当前的代码库:( 有没有办法仍然实现我想要的功能?
  • 我不相信 Json.NET 中包含该功能。您必须自己创建一个图层才能在反序列化之前确定类型。这不是很难做到,但可能会让您在项目的进一步深入时感到头疼。

标签: c# json dictionary serialization json.net


【解决方案1】:

您可以自定义JsonConverter 来处理此问题:

public class CustomDictionaryConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Dictionary<string, AbstractDataObject>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var dict = new Dictionary<string, AbstractDataObject>();
        JObject jo = JObject.Load(reader);
        foreach (JProperty prop in jo.Properties())
        {
            switch (prop.Name)
            {
                case "SomeClass1":
                    dict.Add("SomeClass1", prop.Value.ToObject<SomeClass1>(serializer));
                    break;

                case "SomeClass2":
                    dict.Add("SomeClass2", prop.Value.ToObject<SomeClass2>(serializer));
                    break;
            }
        }
        return dict;
    }

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

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

然后像这样使用它:

Data data = JsonConvert.DeserializeObject<Data>(json, new CustomDictionaryConverter());

小提琴:https://dotnetfiddle.net/ba4wB6

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-25
    • 2012-09-23
    • 2021-06-08
    • 2023-04-01
    • 2020-01-03
    • 2018-08-28
    • 2021-11-14
    • 1970-01-01
    相关资源
    最近更新 更多