it-swarm.com.ru

Как сказать JSON.NET десериализовать JArray в List <объект>, когда указан тип объекта?

Давайте иметь следующий класс:

class Foo
{
    public object Any;
}

Этот класс принимает все в поле Any.

Когда я звоню:

JsonConvert.DeserializeObject<Foo>("{any: 5}")

Any содержит System.Int64.

Тем не менее, когда я звоню:

JsonConvert.DeserializeObject<Foo>("{any: [5]}")

Any содержит Newtonsoft.Json.Linq.JArray.

Как настроить JSON.NET так, чтобы в этом случае Any содержал List<object>?

УТОЧНЕНИЕ:  

Там может быть что угодно, я могу позвонить:

JsonConvert.DeserializeObject<Foo>("{any: 'c'}")

или же 

JsonConvert.DeserializeObject<Foo>("{any: ['c', 5]}")

Дополнительные разъяснения:

Я хотел бы сказать как-то JSON.NET (возможно, с помощью JsonSerializerSettings):

Когда вы встретите object и JSON содержит массив, десериализуйте его (например) List<object>.

7
TN.

В настоящее время я издевался над следующим решением:

public class MyObjectConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(object);
    }

    public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        switch (reader.TokenType)
        {
            case Newtonsoft.Json.JsonToken.StartArray:
                return JToken.Load(reader).ToObject<List<object>>(); 
            case Newtonsoft.Json.JsonToken.StartObject:
                return JToken.Load(reader).ToObject<Dictionary<string, object>>(); 
            default:
                if (reader.ValueType == null && reader.TokenType != Newtonsoft.Json.JsonToken.Null)
                    throw new NotImplementedException("MyObjectConverter");
                return reader.Value;
        }
    }

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

    public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotSupportedException("MyObjectConverter");
    }
}

Проблема этого решения в том, что оно должно обрабатывать и другие типы. Может произойти сбой, когда reader.TokenType не является ни StartArray, ни StartObject, а reader.ValueType имеет значение null. Надеюсь, кто-то предоставит лучшее решение.

2
TN.

Ваш ответ, вероятно, здесь

Ваш [5] является массивом. Все, что вам нужно сделать, это бросить его в список. 


Вы также можете создать свой собственный конвертер, как описано здесь

2
Daniel Möller

Я думаю, что вы могли бы сделать это с помощью JsonConverter. Приведенный ниже преобразователь преобразует JArrays в списки объектов, когда любое поле представляет собой JArray и возвращается к поведению по умолчанию для любых других случаев. Исходя из вашего описания, это именно то, что вы ищете. Я подозреваю, что код можно улучшить, но это должно указать вам путь к решению:

public class ListJsonConverter : 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)
    {
        var theFoo = new Foo();

        dynamic dynamicObject = serializer.Deserialize(reader);

        if (dynamicObject.any.GetType() == typeof (JArray))
        {
            var items = new List<object>();

            foreach (var item in dynamicObject.any)
            {
                items.Add(item);
            }

            theFoo.Any = items;
        }
        else
        {
            theFoo.Any = dynamicObject.any.Value;
        }

        return theFoo;
    }

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

    public override bool CanRead
    {
        get { return true; }
    }

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

Использование:

var bar = JsonConvert.DeserializeObject<Foo>("{any: ['c', 5]}", new ListJsonConverter());
0
Rob Davis