Any way to deserialize this?

Aug 23, 2011 at 9:58 PM

Here's the JSON I'm getting:

[{"page":1,"pages":1,"per_page":"500","total":2},[{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"US","value":"United States"},"value":"14582400000000","decimal":"0","date":"2010"},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"US","value":"United States"},"value":"14043900000000","decimal":"0","date":"2009"}]]

I've tried a few different variations of serialization class but no matter what I keep getting the "Cannot deserialize JSON array into type... " exception.  Is it possible?

Thanks,

tim

Aug 24, 2011 at 4:55 PM

Nevermind, I just wrote myself a custom JsonConverter!

Sep 13, 2011 at 8:27 PM

How did you figure this out? What did you use? I'm doing something similar with WorldBank data and I split it up in to a couple of arrays and did it that way.

 

JArray array = JArray.Parse(output);
var country = JsonConvert.DeserializeObject>(array[1].ToString());

Sep 13, 2011 at 8:45 PM

Sure, here's how I laid out my serialization classes...

 

    [JsonConverter(typeof(WorldBankResponseConverter))]
    public class WorldBankResponse
    {
        public WorldBankResponseHeader Header { get; set; }
        public IList<WorldBankResponseDataPoint> DataPoints { get; set; }
    }

    public class WorldBankResponseHeader
    {
        public int Page { get; set; }
        public int Pages { get; set; }
        [JsonProperty("per_page")]
        public int PerPage { get; set; }
        public int Total { get; set; }
    }

    public class WorldBankResponseDataPoint
    {
        public IdDataPoint Indicator { get; set; }
        public IdDataPoint Country { get; set; }
        public double? Value { get; set; }
        public double? Decimal { get; set; }
        public string Date { get; set; }
    }

    public class IdDataPoint
    {
        public string Id { get; set; }
        public string Value { get; set; }
    }

 

Then I wrote a custom JSON converter which eats the start and end of the array, fills the header with the first element read and fills the list of datapoints with the remaining element.  It looks like this:

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

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            // get to the start of the header
            if (reader.TokenType == JsonToken.StartArray)
                reader.Read();

            var obj = new WorldBankResponse {Header = new WorldBankResponseHeader(), DataPoints = new List<WorldBankResponseDataPoint>()};
            serializer.Populate(reader, obj.Header);
            reader.Read();
            serializer.Populate(reader, obj.DataPoints);

            // now read the end array
            if (reader.TokenType == JsonToken.EndArray)
                reader.Read();

            return obj;
        }

        public override bool CanConvert(Type objectType)
        {
            return objectType.Equals(typeof (WorldBankResponse));
        }
    }

Then I can just deserialize right to a WorldBankResponse like so:

    return JsonConvert.DeserializeObject<WorldBankResponse>(json);