Deserialize JSON when a value can be an object or an empty array

nikita_97_10

I`m working with VK API. Sometimes server can return empty array instead of object, for example:

personal: [] //when it is empty

or

personal: {
religion: 'Нет',
smoking: 1,
alcohol: 4
} //when not empty.

I`m deserializing most of json with JsonConvert.DeserializeObject, and this part of json with

MainObject = ((MainObject["response"].GetObject())["user"].GetObject())["personal"].GetObject();
try
{
Convert.ToByte(MainObject["political"].GetNumber();
} 
catch {}

But it makes app works slowly when it`s handling a lot of exeptions. And just now i realised that here are some more fields that might return array when empty. I just have no ideas how to make it fastly and clearly. Any suggestions?

My deserializing class (doen`t work when field is empty):

     public class User
            {
//some other fields...
                public Personal personal { get; set; }
//some other fields...
             }
    public class Personal
            {
                public byte political { get; set; }
                public string[] langs { get; set; }
                public string religion { get; set; }
                public string inspired_by { get; set; }
                public byte people_main { get; set; }
                public byte life_main { get; set; }
                public byte smoking { get; set; }
                public byte alcohol { get; set; }
            }

Another idea (doesn`t work when not empty):

public List<Personal> personal { get; set; }
dbc

You could make a JsonConverter like the following, that looks for either an object of a specified type, or an empty array. If an object, it deserializes that object. If an empty array, it returns null:

public class JsonSingleOrEmptyArrayConverter<T> : JsonConverter where T : class
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(T).IsAssignableFrom(objectType);
    }

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var contract = serializer.ContractResolver.ResolveContract(objectType);
        if (!(contract is Newtonsoft.Json.Serialization.JsonObjectContract || contract is Newtonsoft.Json.Serialization.JsonDictionaryContract))
        {
            throw new JsonSerializationException(string.Format("Unsupported objectType {0} at {1}.", objectType, reader.Path));
        }

        switch (reader.SkipComments().TokenType)
        {
            case JsonToken.StartArray:
                {
                    int count = 0;
                    while (reader.Read())
                    {
                        switch (reader.TokenType)
                        {
                            case JsonToken.Comment:
                                break;
                            case JsonToken.EndArray:
                                return existingValue;
                            default:
                                {
                                    count++;
                                    if (count > 1)
                                        throw new JsonSerializationException(string.Format("Too many objects at path {0}.", reader.Path));
                                    existingValue = existingValue ?? contract.DefaultCreator();
                                    serializer.Populate(reader, existingValue);
                                }
                                break;
                        }
                    }
                    // Should not come here.
                    throw new JsonSerializationException(string.Format("Unclosed array at path {0}.", reader.Path));
                }

            case JsonToken.Null:
                return null;

            case JsonToken.StartObject:
                existingValue = existingValue ?? contract.DefaultCreator();
                serializer.Populate(reader, existingValue);
                return existingValue;

            default:
                throw new InvalidOperationException("Unexpected token type " + reader.TokenType.ToString());
        }
    }

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

public static partial class JsonExtensions
{
    public static JsonReader SkipComments(this JsonReader reader)
    {
        while (reader.TokenType == JsonToken.Comment && reader.Read())
            ;
        return reader;
    }
}

Then use it like:

public class User
{
    //some other fields...
    [JsonConverter(typeof(JsonSingleOrEmptyArrayConverter<Personal>))]
    public Personal personal { get; set; }
    //some other fields...
}

You should now be able to deserialize a user into your User class.

Notes:

  • The converter can be applied via attributes or in JsonSerializerSettings.Converters.

  • The converter isn't designed to work with simple types such as strings, it's designed for classes that map to a JSON object. That's because it uses JsonSerializer.Populate() to avoid an infinite recursion during reading.

Working sample .Net fiddles here and here.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Json deserialize object empty

From Dev

Empty json object instead of null, when no data -> how to deserialize with gson

From Dev

Jackson Can not deserialize empty array

From Dev

Can Spring MVC deserialize JSON which can be object or array?

From Dev

Deserialize JSON object name-value pairs as elements of an array

From Dev

Deserialize Json Object null value

From Dev

Deserialize JSON object with blank array

From Dev

Can't deserialize json array

From Dev

Json_decode returning empty value - json object to php array

From Dev

Deserialize JSON as object or array with JSON.Net

From Dev

Deserialize array of json objects with json object inside

From Dev

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type because the type requires a JSON array

From Dev

Json.Net deserialize object give me empty object

From Dev

How can I deserialize JSON to Java Object using GSON when the JSON using dates as property names?

From Dev

Gson deserialize JSON array with multiple object types

From Dev

Deserialize JSON structure to object array and dictionary

From Dev

Json newtonsoft : Deserialize string array from an Object

From Dev

Json array object is always empty when posted to mvc actionresult

From Dev

Can't deserialize current json object

From Dev

How let the Json.net return a new T value when the Deserialize Object is null?

From Dev

Can't deserialize the current json array into type

From Dev

I can't deserialize json array

From Dev

Convert JSON to Object throws JsonMappingException "Can not deserialize instance of class out of START_ARRAY token"

From Dev

Can jackson determine root object type to deserialize to when json includes type property?

From Dev

How can I deserialize a JSON array of "name" "value" pairs to a Pojo using Jackson

From Dev

Adding empty array to a JSON object

From Dev

JSON to a JSON array Cannot deserialize the current JSON object

From Java

Cannot deserialize the JSON array (e.g. [1,2,3]) into type ' ' because type requires JSON object (e.g. {"name":"value"}) to deserialize correctly

From Dev

Deserialize json array where attribute value is array java

Related Related

  1. 1

    Json deserialize object empty

  2. 2

    Empty json object instead of null, when no data -> how to deserialize with gson

  3. 3

    Jackson Can not deserialize empty array

  4. 4

    Can Spring MVC deserialize JSON which can be object or array?

  5. 5

    Deserialize JSON object name-value pairs as elements of an array

  6. 6

    Deserialize Json Object null value

  7. 7

    Deserialize JSON object with blank array

  8. 8

    Can't deserialize json array

  9. 9

    Json_decode returning empty value - json object to php array

  10. 10

    Deserialize JSON as object or array with JSON.Net

  11. 11

    Deserialize array of json objects with json object inside

  12. 12

    Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type because the type requires a JSON array

  13. 13

    Json.Net deserialize object give me empty object

  14. 14

    How can I deserialize JSON to Java Object using GSON when the JSON using dates as property names?

  15. 15

    Gson deserialize JSON array with multiple object types

  16. 16

    Deserialize JSON structure to object array and dictionary

  17. 17

    Json newtonsoft : Deserialize string array from an Object

  18. 18

    Json array object is always empty when posted to mvc actionresult

  19. 19

    Can't deserialize current json object

  20. 20

    How let the Json.net return a new T value when the Deserialize Object is null?

  21. 21

    Can't deserialize the current json array into type

  22. 22

    I can't deserialize json array

  23. 23

    Convert JSON to Object throws JsonMappingException "Can not deserialize instance of class out of START_ARRAY token"

  24. 24

    Can jackson determine root object type to deserialize to when json includes type property?

  25. 25

    How can I deserialize a JSON array of "name" "value" pairs to a Pojo using Jackson

  26. 26

    Adding empty array to a JSON object

  27. 27

    JSON to a JSON array Cannot deserialize the current JSON object

  28. 28

    Cannot deserialize the JSON array (e.g. [1,2,3]) into type ' ' because type requires JSON object (e.g. {"name":"value"}) to deserialize correctly

  29. 29

    Deserialize json array where attribute value is array java

HotTag

Archive