Десериализация неизвестного формата JSON - PullRequest
0 голосов
/ 28 мая 2020

РЕДАКТИРОВАТЬ: Мои плохие друзья, я имел в виду десериализацию, а не сериализацию ...

Я пытаюсь интерпретировать ответ JSON, который я получаю с веб-сайта, но есть два проблемы:

1) Первая версия JSON имеет список с неизвестным количеством строк, и я не думаю, что смогу создать класс с членом List<string> {get; set;}.

2) Я не могу знать, какую версию я получу, и для того, чтобы сказать, мне придется проверить значение "Second". Мне интересно, есть ли более простой способ сделать это?

Это два возможных формата:

{ "1":"1", "2":"2", "Second":{ "3":"3", "4":"4", "Third":["5"]}} <-- More things could be in 'Third'
{ "1":"1", "2":"2", "Second":{ "3":"3", "4":"4", "Third":{"5":"5", "6":"6"}}

Я десериализую их с помощью пакета Newtonsoft Json C# и я получить ответ на звонок HttpClient.PostAsync().

1 Ответ

1 голос
/ 29 мая 2020

Десериализация в список должна работать нормально. Как говорит @maytham, собственный конвертер - это путь к go.

Приведенный ниже SpecialArrayConverter должен помочь, если вы примените его к своей модели через атрибут [JsonConverter(typeof(SpecialArrayConverter))].

Как реализовано ниже, он будет читать словарь или массив в json и заполните соответствующую коллекцию в десериализованном классе.

Я ввел свойство как IEnumable<string> по привычке, но List<string> работает точно так же. string [] тоже может работать с небольшой настройкой.

using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Json
{
    class JsonResponseObject
    {
        public string Id { get; set; }

        // Apply our special converter to this property
        [JsonConverter(typeof(SpecialArrayConverter))]
        public IEnumerable<string> ArrayData { get; set; }
    }

    // Our Special Converter
    class SpecialArrayConverter : JsonConverter
    {
        // Read Only
        public override bool CanWrite => false;

        // We only work with IEnumerable<string> && IDictionary<string, string>
        public override bool CanConvert(Type objectType)
        {
            return objectType.IsAssignableFrom(typeof(IEnumerable<string>)) || objectType.IsAssignableFrom(typeof(IDictionary<string, string>));
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JToken token;

            switch (reader.TokenType)
            {
                // If it's an array, read the token parse it
                // into an array and proceeed
                case JsonToken.StartArray:
                    token = JToken.Load(reader);
                    return token.ToObject<List<string>>();

                // If it's an object, it must be a dictionary
                // parse it into a dictionary and then
                // output the keys into an array and
                // return that
                case JsonToken.StartObject:
                    token = JToken.Load(reader);
                    var data = token.ToObject<Dictionary<string, string>>();
                    return data
                        .Select(data => data.Key)
                        .ToList();
                default:
                    throw new JsonSerializationException();
            }
        }

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

    class Program
    {
        static void Main(string[] args)
        {
            var a = JsonConvert.SerializeObject(new
            {
                ArrayData = new Dictionary<string, string>
                {
                    { "5", "5" },
                    { "6", "6" }
                }
            });
            var b = JsonConvert.SerializeObject(new
            {
                ArrayData = new List<string>
                {
                    "5",
                    "6"
                }
            });

            var resulta = JsonConvert.DeserializeObject<JsonResponseObject>(a);
            var resultb = JsonConvert.DeserializeObject<JsonResponseObject>(b);

            Console.WriteLine("Hello World!");
        }
    }
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...