JKhuang
JKhuang

Reputation: 1553

How to deserialize JSON data which sometimes is an empty array and sometimes a string value

I get JSON data from server, but I found, when the string value was empty the server return a empty array. Not a blank string (""). So I confuse how to handle this case, I am using JSON.NET to deserialize JSON data, should I override the ReadJson method in JsonConverter? Thank everyone advance!

Detail Description

Due to in WeiboPOI class, I defined Poiid and Address as string, when the server returns string data, my program can deserialize the JSON data normally, but when Poiid or Address is empty, the server returns an empty array, not a blank string (""), so my program can't deserilize the JSON data.

JSON data

{
  "pois": [
    {
      "pid": "P01QN07N6S5",
      "longitude": "109.53466",
      "latitude": "26.96971",
      "name": "TEST1",
      "city_name": "TEST1",
      "province_name": "TEST1",
      "address": [

      ],
      "telephone": "",
      "category": "190108",
      "navigator": "",
      "pic_url": ""
    },
    {
      "pid": [

      ],
      "longitude": "113.32608",
      "latitude": "23.15884",
      "name": "TEST2",
      "city_name": "TEST2",
      "province_name": "TEST2",
      "address": "Test address",
      "telephone": "020-61089463",
      "category": "60000",
      "navigator": "",
      "pic_url": ""
    }
  ],
  "total_number": "68467"
}

Image

enter image description here

DTO

public class WeiboPOI : IWeiboModel
{
[DataMember]
public string Poiid { get; set; }

[DataMember]
public string Title { get; set; }

// This is a string value not array.
// So the server returns an empty array will have an exception.
[DataMember]
public string Address { get; set; }

[JsonProperty("lon")]
public string Longitude { get; set; }

[JsonProperty("Lat")]
public string Latitude { get; set; }

[DataMember]
public string Category { get; set; }

[DataMember]
public string City { get; set; }

[DataMember]
public string Province { get; set; }

[DataMember]
public string Country { get; set; }

[DataMember]
public string Url { get; set; }

[DataMember]
public string Phone { get; set; }

[DataMember]
public string Postcode { get; set; }

[DataMember]
public string WeiboId { get; set; }

[DataMember]
public string Icon { get; set; }

[DataMember]
public string Extra { get; set; }

[DataMember]
public string Rid { get; set; }

[DataMember]
public string Categorys { get; set; }

[DataMember]
public string CategoryName { get; set; }

[DataMember]
public string CheckinUserNum { get; set; }

[DataMember]
public string PoiPic { get; set; }

[DataMember]
public int Pintu { get; set; }

[DataMember]
public string PoiStreetAddress { get; set; }

[DataMember]
public string PoiStreetSummary { get; set; }

[DataMember]
public int Enterprise { get; set; }

[DataMember]
public string CheckinTime { get; set; }

public string RawSource { get; set; }
}

Upvotes: 4

Views: 4660

Answers (1)

Athari
Athari

Reputation: 34295

Writing a custom JsonConverter for a primitive type is pretty straghtforward:

using System;
using Newtonsoft.Json;

namespace So17171737_ArrayOrString
{
    class StringOrArrayConverter : JsonConverter
    {
        public override object ReadJson (JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            switch (reader.TokenType) {
                case JsonToken.String:
                case JsonToken.Null:
                    return reader.Value;
                case JsonToken.StartArray:
                    reader.Read();
                    if (reader.TokenType != JsonToken.EndArray)
                        throw new JsonReaderException("Empty array expected.");
                    return "";
            }
            throw new JsonReaderException("Expected string or null or empty array.");
        }

        public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
        {
            serializer.Serialize(writer, value);
        }

        public override bool CanConvert (Type objectType)
        {
            return objectType == typeof(string);
        }
    }

    class Program
    {
        private const string json = @"
{
    s1: 'str1',
    s2: [],
    s3: null
}
";

        static void Main ()
        {
            Foo foo = JsonConvert.DeserializeObject<Foo>(json, new JsonSerializerSettings {
                Converters = { new StringOrArrayConverter() }
            });
            Console.WriteLine(JsonConvert.SerializeObject(foo, Formatting.Indented));
            Console.ReadKey();
        }

        class Foo
        {
            public string s1, s2, s3;
        }
    }
}

This code overrides deserialization of all string values. If you need this only for specific members, you need to apply JsonConverterAttribute.

Upvotes: 2

Related Questions