在反序列化JSON时,是否可以添加将组合多个json属性的其他类型?

时间:2017-12-08 15:52:19

标签: c# json json.net json-deserialization

原始的JSON C#类结构看起来像

 public class Main
    {
        public double temp { get; set; }
        public double temp_min { get; set; }
        public double temp_max { get; set; }
        public double pressure { get; set; }
        public double sea_level { get; set; }
        public double grnd_level { get; set; }
        public int humidity { get; set; }
        public double temp_kf { get; set; }
    }

    public class Weather
    {
        public int id { get; set; }
        public string main { get; set; }
        public string description { get; set; }
        public string icon { get; set; }
    }

    public class Clouds
    {
        public int all { get; set; }
    }

    public class Wind
    {
        public double speed { get; set; }
        public double deg { get; set; }
    }

    public class Snow
    {
        public double? 3h { get; set; }
    }

    public class Sys
    {
        public string pod { get; set; }
    }

    public class Rain
    {
        public double 3h { get; set; }
    }

    public class List
    {
        public int dt { get; set; }
        public Main main { get; set; }
        public IList<Weather> weather { get; set; }
        public Clouds clouds { get; set; }
        public Wind wind { get; set; }
        public Snow snow { get; set; }
        public Sys sys { get; set; }
        public string dt_txt { get; set; }
        public Rain rain { get; set; }
    }

    public class Coord
    {
        public double lat { get; set; }
        public double lon { get; set; }
    }

    public class City
    {
        public int id { get; set; }
        public string name { get; set; }
        public Coord coord { get; set; }
        public string country { get; set; }
    }

    public class Example
    {
        public string cod { get; set; }
        public double message { get; set; }
        public int cnt { get; set; }
        public IList<List> list { get; set; }
        public City city { get; set; }
    }

我想删除一些属性并将其他属性合并到我的类型中,所以最后我想得到下一个C#类结构:

public class WeatherForecast
    {
        [JsonProperty("city")]
        public City City { get; set; }

        [JsonProperty("list")]
        public IList<ClimateIndicators> ClimateIndicators { get; set; }
    }

 public class ClimateIndicators
    {
        public Atmospheric Atmospheric { get; set; }
        public Hydrospheric Hydrospheric { get; set; }
        public Lithospheric Lithospheric { get; set; }
        public DateTime Date { get; set; }

        public IList<WeatherDetails> WeatherDetails { get; set; }
    }

 public class Atmospheric
    {
        [JsonProperty("pressure")]
        public double Pressure { get; set; }
        [JsonProperty("humidity")]
        public int Humidity { get; set; }
        [JsonProperty("sea_level")]
        public double SeaLevel { get; set; }
        [JsonProperty("grnd_level")]
        public double GroundLevel { get; set; }
        [JsonProperty("all")]
        public int Cloudiness { get; set; }
        [JsonProperty("rain")]
        public double? Rain { get; set; }
        [JsonProperty("snow")]
        public double? Snow { get; set; } 
    }

我正在为天气状况添加自定义分类。所以我面临的问题是我不知道如何将多个JSON属性合并到一个属于另一个JSON属性的类中。

1 个答案:

答案 0 :(得分:2)

由于您想要的类结构具有与JSON不同的形状,因此您需要创建自定义JsonConverter来弥合差异。在您的情况下,WeatherForecastCity类不需要任何特殊处理(仅使用[JsonProperty]属性就足够了),但ClimateIndicators类肯定需要转换器。

这是代码中的样子。转换器的工作原理是将list数组的每个项目的JSON数据加载到临时JObject中。 (Json.Net为每个项目调用ReadJson一次,这就是转换器中没有循环的原因。)从那里,SelectToken用于从所需的各种嵌套项属性中选择值填充ClimateIndicators类及其支持类Atmospheric的实例。然后将ClimateIndicators实例返回给Json.Net,Json.Net会自动将其添加到WeatherForecast类的列表中。

class ClimateIndicatorsConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(ClimateIndicators);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = JObject.Load(reader);

        Atmospheric atm = new Atmospheric();
        atm.Pressure = (double)obj.SelectToken("main.pressure");
        atm.Humidity = (int)obj.SelectToken("main.humidity");
        atm.SeaLevel = (double)obj.SelectToken("main.sea_level");
        atm.GroundLevel = (double)obj.SelectToken("main.grnd_level");
        atm.Cloudiness = (int)obj.SelectToken("clouds.all");
        atm.Rain = (double?)obj.SelectToken("rain.3h");
        atm.Snow = (double?)obj.SelectToken("snow.3h");

        ClimateIndicators indicators = new ClimateIndicators();
        indicators.Atmospheric = atm;
        indicators.Date = (DateTime)obj.SelectToken("dt_txt");

        return indicators;
    }

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

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

要使用转换器,请向[JsonConverter]类添加ClimateIndicators属性,如下所示:

    [JsonConverter(typeof(ClimateIndicatorsConverter))]
    public class ClimateIndicators
    {
        ...
    }

请注意,[JsonProperty]ClimateIndicators类中的属性不需要Atmospheric属性,因为转换器正在处理属性映射。

这是一个有效的演示:https://dotnetfiddle.net/Fc9G69