C# Newtonsoft JSON - 使用未知对象集合反序列化对象

标签 c# json json.net

我正在努力使用 newtonsoft.json 对 json 文件进行反序列化.
我要反序列化的对象如下所示:

public class Device
{
        public string Name { get; set; }
        public int Id { get; set; }
        public string Type { get; set; }

        public List<Sensor> Sensors { get; }

        public bool IsPaired { get; set; }

}

传感器类是虚拟的。
我有多个类继承自 Sensor 类(TemperatureSensor、WaterLevelSensor 等)并添加了一些新属性。这些类的实例存储在 Sensors 集合中。

Json 文件如下所示:

[  
   {  
      "Name":"Device1",
      "Id":0,
      "Type":"TemperatureSensor",
      "Sensors":[  
         {  
            "Id":0,
            "Type":"TemperatureSensor",
            "Data":18.136218099999997,
            "ReadIntervalInMiliseconds":5000
         },
         {  
            "Id":1,
            "Type":"TemperatureSensor",
            "Data":18.0999819,
            "ReadIntervalInMiliseconds":5000
         }
      ],
      "IsPaired":false
   },
   {  
      "Name":"Device2",
      "Id":1,
      "Type":"AutomaticGate",
      "Sensors":[  
         {  
            "OpenPercentage":0,
            "Id":0,
            "Type":"AutomaticGate",
            "Data":0.0,
            "ReadIntervalInMiliseconds":0
         }
      ],
      "IsPaired":false
   },
   {  
      "Name":"Device3",
      "Id":2,
      "Type":"Other",
      "Sensors":[  
         {  
            "IsActive":false,
            "Id":0,
            "Type":"AirConditioner",
            "Data":0.0,
            "ReadIntervalInMiliseconds":0
         },
         {  
            "Id":1,
            "Type":"LightSensor",
            "Data":4.0,
            "ReadIntervalInMiliseconds":5000
         }
      ],
      "IsPaired":false
   }
]

我假设我必须从 json 文件中读取传感器的“类型”,并在此基础上创建对象并将其添加到某个集合中,然后使用该集合返回设备类对象。

我正在尝试像这个 blog post 中那样制作自定义 JsonConverter但收效甚微。

最佳答案

您可以创建自定义 JsonConverter 以将 Sensor 对象转换为具体的派生类。以下是此类 JsonConverter 的工作示例:

public class SensorConverter : JsonConverter
{
    public override bool CanRead => true;
    public override bool CanWrite => false;
    public override bool CanConvert(Type objectType)
    {
        // Don't do IsAssignableFrom tricks here, because you only know how to convert the abstract class Sensor.
        return objectType == typeof(Sensor);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jObject = JObject.Load(reader);
        string sensorType = jObject["Type"].Value<string>();
        switch (sensorType)
        {
            case "TemperatureSensor":
                return jObject.ToObject<TemperatureSensor>(serializer);
            case "AutomaticGate":
                return jObject.ToObject<AutomaticGate>(serializer);
            case "AirConditioner":
                return jObject.ToObject<AirConditioner>(serializer);
            case "LightSensor":
                return jObject.ToObject<LightSensor>(serializer);
            default:
                throw new NotSupportedException($"Sensor type '{sensorType}' is not supported.");
        }
    }

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

然后,在反序列化时,您必须将自定义转换器添加到设置中才能使其正常工作。

请注意,您的 Sensors 属性目前是只读的。您必须提供一个 setter 以便 NewtonSoft 填充该属性。

关于C# Newtonsoft JSON - 使用未知对象集合反序列化对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57478056/

相关文章:

c# - Delegate.CreateDelegate - 方法参数不兼容

c# - 我怎样才能在 C# 中获得真正的操作系统版本?

node.js - npm 命令不更新 json

jquery - 使用数据表 jquery 插件填充数据表时,如果使用 JSON 对象出现自定义异常,则抛出 ajax 错误

php - symfony 从 json 数据中保留日期时间

c# - 读取JSON文件时keyvaluepair值为0

c# - 字符串比较 : InvariantCultureIgnoreCase vs OrdinalIgnoreCase?

c# - Newtonsoft.Json 试图猜测 token 类型并弄错了

c# - 带有正则表达式的 JToken.SelectToken 用于查找与模式匹配的值?

c# - 在哪里定义 DbContext