C# 使用Json.NET为具有多个值类型的字段自定义反序列化器
我有一个JSON文件,其中温度有时是一个数字(版本1),有时是一个对象(版本2): 为了表示这两种“几乎相等”的格式,我只希望有一个类(可能?)带有用于C# 使用Json.NET为具有多个值类型的字段自定义反序列化器,c#,json,json.net,C#,Json,Json.net,我有一个JSON文件,其中温度有时是一个数字(版本1),有时是一个对象(版本2): 为了表示这两种“几乎相等”的格式,我只希望有一个类(可能?)带有用于温度的自定义转换器所有其他字段将自动转换: public class Forecast { private Coordinates _coord = new Coordinates(); private Temperature _temperature = new Temperature(); // json.net w
温度的自定义转换器所有其他字段将自动转换:
public class Forecast {
private Coordinates _coord = new Coordinates();
private Temperature _temperature = new Temperature();
// json.net will do everything to convert 'lat' in a double
[JsonProperty("lat")]
public double Latitude {
get => _coord.Latitude;
set => _coord.Latitude = value;
}
// json.net will do everything to convert 'lon' in a double
[JsonProperty("lon")]
public double Longitude {
get => _coord.Longitude;
set => _coord.Longitude = value;
}
// json.net will do everything to convert 'timezone' in a string
[JsonProperty("timezone")]
public string TimeZone{ get; set; }
// HERE I WANT TO USE A CUSTOM CONVERTER THAT HANDLES the 2 VERSIONS of 'temp' IN THE PROPER WAY.
// THE CODE BELOW DOES NOT WORK AT ALL!
[JsonProperty("temperature", ItemConverterType = typeof(MyTemperatureConverter))]
public Object Temp {
get => _temperature; // return a Temperature object
set {
// do something here to handle it? E.g.:
if (value is Double) {
// it is a ver. 1
_temperature.Avg = (value as double);
} else {
// it is a ver. 2
_temperature.Max = (value as Temperature).Max;
_temperature.Min = (value as Temperature).Min;
}
}
}
}
public class Coordinates {
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public class Temperature {
public double? Avg { get; set; }
public double? Min { get; set; }
public double? Max { get; set; }
}
下面是我的(假设的)反序列化程序:
public class MyTemperatureConverter : JsonConverter {
public override void WriteJson(JsonWriter writer, [AllowNull] object value, JsonSerializer serializer) {
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer) {
// WHAT TO DO HERE?
}
}
下面是我阅读JSON的一般代码:
protected virtual async Task<Forecast> ParseForecastFromResponse(HttpResponseMessage response) {
using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) {
using (var jsonReader = new Newtonsoft.Json.JsonTextReader(new System.IO.StreamReader(responseStream))) {
var serializer = new Newtonsoft.Json.JsonSerializer();
return serializer.Deserialize<Forecast>(jsonReader);
}
}
}
受保护的虚拟异步任务ParseForecastFromResponse(HttpResponseMessage响应){
使用(var responseStream=await response.Content.ReadAsStreamAsync().ConfigureAwait(false)){
使用(var jsonReader=newnewtonsoft.Json.JsonTextReader(new System.IO.StreamReader(responseStream))){
var serializer=newnewtonsoft.Json.JsonSerializer();
返回序列化程序。反序列化(jsonReader);
}
}
}
问题是:我在正确的轨道上吗?或者我需要换个方向吗?您可以制作一个转换器来处理这两种格式,如下所示:
public class MyTemperatureConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Temperature);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
Temperature temp = new Temperature();
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Object)
{
temp.Min = (double?)token["min"];
temp.Max = (double?)token["max"];
}
else
{
temp.Avg = (double?)token;
}
return temp;
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
[JsonProperty("temperature"), JsonConverter(typeof(MyTemperatureConverter))]
public Temperature Temperature { get; set; } = new Temperature();
在Forecast
类中,Temperature
属性的定义和注释如下:
public class MyTemperatureConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Temperature);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
Temperature temp = new Temperature();
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Object)
{
temp.Min = (double?)token["min"];
temp.Max = (double?)token["max"];
}
else
{
temp.Avg = (double?)token;
}
return temp;
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
[JsonProperty("temperature"), JsonConverter(typeof(MyTemperatureConverter))]
public Temperature Temperature { get; set; } = new Temperature();
这是一个正在运行的演示:您能否共享一个类,特别是当前的温度
类以及可以编译的代码?我试着把你的代码粘贴到一把小提琴上,结果发现有几十个编译错误,请看@dbc Temperature只是一个简单的POCO类,具有Min、Max和Avg属性。顺便说一句,解决方案由Brian提供,如下所示。谢谢,这正是我想要的!很高兴我能帮忙!