[英]C# Newtonsoft JSON - Deserializing Object with collection of unknown objects
我正在努力使用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文件讀取Sensor的“類型”,並在此基礎上創建Object並將其添加到某個集合中,然后使用該集合返回Device類對象。
我試圖像在本博文中那樣制作自定義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可以填充該屬性。
另一個需要更少代碼的解決方案是使用JsonSubTypes
假設有一個抽象的Sensor
類,則需要通過自定義屬性注冊一個已知的子類及其標識符。 因此,在您的情況下,標識符是名為"Type"
屬性,而類映射在KnownSubType
屬性中。
[JsonConverter(typeof(JsonSubtypes), "Type")]
[JsonSubtypes.KnownSubType(typeof(TemperatureSensor), "TemperatureSensor")]
[JsonSubtypes.KnownSubType(typeof(WaterLevelSensor), "WaterLevelSensor")]
[JsonSubtypes.KnownSubType(typeof(AirConditioner), "AirConditioner")]
[JsonSubtypes.KnownSubType(typeof(AutomaticGate), "AutomaticGate")]
[JsonSubtypes.KnownSubType(typeof(LightSensor), "LightSensor")]
public abstract class Sensor
{
}
在您的Device類中, Sensors
屬性必須具有set
屬性。
public List<Sensor> Sensors { get; set;}
用法:
var items = JsonConvert.DeserializeObject<List<Device>>(json);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.