反序列化未知的JSON格式

问题描述 投票:0回答:1

编辑:我的兄弟,我的意思是反序列化而不是序列化...

我正在尝试解释从网站获得的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()调用中收到响应。

c# json.net
1个回答
0
投票

反序列化到列表应该可以。正如@maytham所说,自定义转换器是必经之路。

如果通过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!");
        }
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.