Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Json.NET为具有多个值类型的字段自定义反序列化器_C#_Json_Json.net - Fatal编程技术网

C# 使用Json.NET为具有多个值类型的字段自定义反序列化器

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

我有一个JSON文件,其中温度有时是一个数字(版本1),有时是一个对象(版本2):

为了表示这两种“几乎相等”的格式,我只希望有一个类(可能?)带有用于
温度的自定义转换器所有其他字段将自动转换

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提供,如下所示。谢谢,这正是我想要的!很高兴我能帮忙!