0

I'm trying use json to get weather information from climatempo api, but I'm getting this error bellow, because one of the items is an array, I've tryed to change from:

public static ClimaTempo15 FromJson(string json) => JsonConvert.DeserializeObject<ClimaTempo15>(json, NewWeatherImage15.Converter.Settings);

To

   public static List<ClimaTempo15> FromJson(string json) => JsonConvert.DeserializeObject<List<ClimaTempo15>>(json, NewWeatherImage15.Converter.Settings);

but I'm still geting the same error

The Json is here https://pastebin.com/pfYzihSM

Message=Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[NewWeatherImage15.Datum]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.

namespace NewWeatherImage15
{
    using System;
    using System.Collections.Generic;

    using System.Globalization;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;

    public partial class ClimaTempo15
    {
        [JsonProperty("id")]
        public long Id { get; set; }

        [JsonProperty("name")]
        public string Name { get; set; }

        [JsonProperty("state")]
        public string State { get; set; }

        [JsonProperty("country")]
        public string Country { get; set; }

        [JsonProperty("meteogram")]
        public Uri Meteogram { get; set; }

        [JsonProperty("data")]
        public List<Datum> Data { get; set; }
    }

    public partial class Datum
    {
        [JsonProperty("date")]
        public DateTimeOffset Date { get; set; }

        [JsonProperty("date_br")]
        public string DateBr { get; set; }

        [JsonProperty("humidity")]
        public Humidity Humidity { get; set; }

        [JsonProperty("rain")]
        public Rain Rain { get; set; }

        [JsonProperty("wind")]
        public Wind Wind { get; set; }

        [JsonProperty("thermal_sensation")]
        public ThermalSensation ThermalSensation { get; set; }

        [JsonProperty("text_icon")]
        public TextIcon TextIcon { get; set; }

        [JsonProperty("temperature")]
        public Humidity Temperature { get; set; }

        [JsonProperty("cloud_coverage")]
        public CloudCoverage CloudCoverage { get; set; }

        [JsonProperty("sun")]
        public Sun Sun { get; set; }
    }

    public partial class CloudCoverage
    {
        [JsonProperty("low")]
        public long Low { get; set; }

        [JsonProperty("mid")]
        public long Mid { get; set; }

        [JsonProperty("high")]
        public long High { get; set; }

        [JsonProperty("dawn")]
        public CloudCoverageAfternoon Dawn { get; set; }

        [JsonProperty("morning")]
        public CloudCoverageAfternoon Morning { get; set; }

        [JsonProperty("afternoon")]
        public CloudCoverageAfternoon Afternoon { get; set; }

        [JsonProperty("night")]
        public CloudCoverageAfternoon Night { get; set; }
    }

    public partial class CloudCoverageAfternoon
    {
        [JsonProperty("low")]
        public long Low { get; set; }

        [JsonProperty("mid")]
        public long Mid { get; set; }

        [JsonProperty("high")]
        public long High { get; set; }
    }

    public partial class Humidity
    {
        [JsonProperty("min")]
        public long Min { get; set; }

        [JsonProperty("max")]
        public long Max { get; set; }

        [JsonProperty("dawn")]
        public ThermalSensation Dawn { get; set; }

        [JsonProperty("morning")]
        public ThermalSensation Morning { get; set; }

        [JsonProperty("afternoon")]
        public ThermalSensation Afternoon { get; set; }

        [JsonProperty("night")]
        public ThermalSensation Night { get; set; }
    }

    public partial class ThermalSensation
    {
        [JsonProperty("min")]
        public long Min { get; set; }

        [JsonProperty("max")]
        public long Max { get; set; }
    }

    public partial class Rain
    {
        [JsonProperty("probability")]
        public long Probability { get; set; }

        [JsonProperty("precipitation")]
        public long Precipitation { get; set; }
    }

    public partial class Sun
    {
        [JsonProperty("sunrise")]
        public DateTimeOffset Sunrise { get; set; }

        [JsonProperty("sunset")]
        public DateTimeOffset Sunset { get; set; }
    }

    public partial class TextIcon
    {
        [JsonProperty("icon")]
        public Icon Icon { get; set; }

        [JsonProperty("text")]
        public Text Text { get; set; }
    }

    public partial class Icon
    {
        [JsonProperty("dawn")]
        public string Dawn { get; set; }

        [JsonProperty("morning")]
        public string Morning { get; set; }

        [JsonProperty("afternoon")]
        public string Afternoon { get; set; }

        [JsonProperty("night")]
        public string Night { get; set; }

        [JsonProperty("day", NullValueHandling = NullValueHandling.Ignore)]
        [JsonConverter(typeof(ParseStringConverter))]
        public long? Day { get; set; }

        [JsonProperty("reduced", NullValueHandling = NullValueHandling.Ignore)]
        public string Reduced { get; set; }
    }

    public partial class Text
    {
        [JsonProperty("pt")]
        public string Pt { get; set; }

        [JsonProperty("en")]
        public string En { get; set; }

        [JsonProperty("es")]
        public string Es { get; set; }

        [JsonProperty("phrase")]
        public Icon Phrase { get; set; }
    }

    public partial class Wind
    {
        [JsonProperty("velocity_min")]
        public long VelocityMin { get; set; }

        [JsonProperty("velocity_max")]
        public long VelocityMax { get; set; }

        [JsonProperty("velocity_avg")]
        public long VelocityAvg { get; set; }

        [JsonProperty("gust_max")]
        public long GustMax { get; set; }

        [JsonProperty("direction_degrees")]
        public long DirectionDegrees { get; set; }

        [JsonProperty("direction")]
        public string Direction { get; set; }

        [JsonProperty("dawn")]
        public WindAfternoon Dawn { get; set; }

        [JsonProperty("morning")]
        public WindAfternoon Morning { get; set; }

        [JsonProperty("afternoon")]
        public WindAfternoon Afternoon { get; set; }

        [JsonProperty("night")]
        public WindAfternoon Night { get; set; }
    }

    public partial class WindAfternoon
    {
        [JsonProperty("direction")]
        public string Direction { get; set; }

        [JsonProperty("direction_degrees")]
        public long DirectionDegrees { get; set; }

        [JsonProperty("gust_max")]
        public long GustMax { get; set; }

        [JsonProperty("velocity_max")]
        public long VelocityMax { get; set; }

        [JsonProperty("velocity_avg")]
        public long VelocityAvg { get; set; }
    }

    public partial class ClimaTempo15
    {
          public static ClimaTempo15 FromJson(string json) => JsonConvert.DeserializeObject<ClimaTempo15>(json, NewWeatherImage15.Converter.Settings);
       // public static List<ClimaTempo15> FromJson(string json) => JsonConvert.DeserializeObject<List<ClimaTempo15>>(json, NewWeatherImage15.Converter.Settings);
    }

    public static class Serialize
    {
        public static string ToJson(this ClimaTempo15 self) => JsonConvert.SerializeObject(self, NewWeatherImage15.Converter.Settings);
    }

    internal static class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters =
            {
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }

    internal class ParseStringConverter : JsonConverter
    {
        public override bool CanConvert(Type t) => t == typeof(long) || t == typeof(long?);

        public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null) return null;
            var value = serializer.Deserialize<string>(reader);
            long l;
            if (Int64.TryParse(value, out l))
            {
                return l;
            }
            throw new Exception("Cannot unmarshal type long");
        }

        public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
        {
            if (untypedValue == null)
            {
                serializer.Serialize(writer, null);
                return;
            }
            var value = (long)untypedValue;
            serializer.Serialize(writer, value.ToString());
            return;
        }

        public static readonly ParseStringConverter Singleton = new ParseStringConverter();
    }
}
3
  • Try using IEnumerable<Datum> - "e.g. not a primitive type like integer, not a collection type like an array or List" Commented Aug 22, 2019 at 17:37
  • 1
    I have copy-pasted your code and run it this way: static void Main(string[] args){using (var sr = new StreamReader(@"c:\Users\Kristóf\Documents\asd.json")){var des = ClimaTempo15.FromJson(sr.ReadToEnd());}} It worked like charm... (Sorry the awful formatting) Commented Aug 22, 2019 at 17:43
  • 1
    Your sample JSON is just a single object. What would it look like for multiple objects? Commented Aug 22, 2019 at 17:54

1 Answer 1

4

Your model matches the json object so there is no issue there.

This code should work properly

JsonConvert.DeserializeObject<ClimaTempo15>(json, NewWeatherImage15.Converter.Settings)

Are you sure you're getting the JSON you think you're getting? Often if there is a single value in an array you will get an object instead of array of objects from the API.

Array

"data": [
  {"id": "1"},
  {"id": "2"}
]

Single object

"data": 
  {"id": "1"}

Working C# fiddle: https://dotnetfiddle.net/BXKhbm

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.