4

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; }
}
Athari
  • 33,702
  • 16
  • 105
  • 146
JKhuang
  • 1,523
  • 2
  • 12
  • 14
  • I hardly can understand your question, please describe the situation in more details. – Zoltán Tamási Jun 18 '13 at 14:42
  • Hello. I think i not understand your problem correctly. If your array is empty, no data was returned. What the problem with that? – Jhonatas Kleinkauff Jun 18 '13 at 14:43
  • 1
    Can you post your C# code that you're using to deserialize this? – Joe Enos Jun 18 '13 at 14:43
  • I'm confused by the question. The input JSON is specifying an empty array for the first element's address and second element's pid -- your JSON deserializer is properly reading the data you are retrieving. It looks like the server component is generating the wrong JSON. – wgraham Jun 18 '13 at 14:48
  • 1
    Looks like an error in your server software. I'd fix that rather than workaround the problem on the client. If you can't fix the server, you need to implement custom `JsonConverter`. For a similar example, see http://stackoverflow.com/a/16977074/293099 – Athari Jun 18 '13 at 14:56
  • Yes, I can't fix the server data issue. – JKhuang Jun 19 '13 at 04:38
  • @Joe Enos, please see my detail description, thank you. – JKhuang Jun 19 '13 at 04:42

1 Answers1

2

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.

Athari
  • 33,702
  • 16
  • 105
  • 146