簡體   English   中英

JSON.NET中屬性的序列化引發異常

[英]Serialization of properties in JSON.NET throws Exception

這是一個示例應用程序,顯示了使用JsonConverter進行列表的自定義序列化。 我向JsonConvert注冊了一個自定義JsonSerializerSettings。 這些設置安裝了我的ListOfGuidConverter。

當您將List序列化和反序列化為序列化的根對象時,這可以很好地工作。 一旦擁有另一個根對象並且List是一個屬性,JSON.Net就會引發異常,表示意外結束。

我該怎么做才能解決此問題?

謝謝Rich

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using PB8.Peep;

namespace JsonTest
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var ListOfGuidsConverter = new ListJsonConverter<Guid>();
                var jss = new JsonSerializerSettings();
                jss.Converters.Add(new ListofGuidJsonConverter());

                string value1 = JsonConvert.SerializeObject(GetSampleList());
                Console.WriteLine(value1);

                JsonConvert.DefaultSettings = () => jss;

                string value2 = JsonConvert.SerializeObject(GetSampleList());
                Console.WriteLine();
                Console.WriteLine(value2);

                var value3 = JsonConvert.DeserializeObject<List<Guid>>(value2);

                string value4 = JsonConvert.SerializeObject(value3);

                Console.WriteLine();
                Console.WriteLine(value4);

                var value5 = JsonConvert.SerializeObject(GetSample());
                Console.WriteLine();
                Console.WriteLine(value5);

                var value6 = JsonConvert.DeserializeObject<Sample>(value5);

                var value7 = JsonConvert.SerializeObject(value6);

                Console.WriteLine();
                Console.WriteLine(value7);

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            finally
            {
                Console.ReadLine();
            }
        }

        public static List<Guid> GetSampleList()
        {
            return new List<Guid>
            {
                Guid.NewGuid(),
                Guid.NewGuid(),
                Guid.NewGuid()
            };
        }

        public static Sample GetSample()
        {
            Sample s = new Sample();
            s.List1.Add(Guid.NewGuid());
            s.List1.Add(Guid.NewGuid());
            s.List1.Add(Guid.NewGuid());
            s.List1.Add(Guid.NewGuid());
            s.List1.Add(Guid.NewGuid());

            return s;
        }

        public class Sample
        {
            public Sample()
            {
                List1 = GetSampleList();
            }

            public List<Guid> List1 { get; set; }
        }
    }




    public class ListofGuidJsonConverter : JsonConverter
    {
        private const string CapacityPropertyName = "c";
        private const string ListPropertyName = "l";
        private static readonly Type _type = typeof(List<Guid>);

        public override bool CanConvert(Type objectType)
        {
            bool canConvert = objectType == _type;
            return canConvert;
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            const int DefaultCapacity = 4;

            if (reader.TokenType == JsonToken.StartObject)
                reader.Read();

            if (reader.TokenType == JsonToken.PropertyName)
                reader.Read();

            int capacity = DefaultCapacity;
            if (reader.TokenType == JsonToken.Integer)
            {
                capacity = Convert.ToInt32(reader.Value);
                reader.Read();
            }

            var listOfT = new List<Guid>(capacity);

            if (reader.TokenType == JsonToken.PropertyName)
                reader.Read();

            if (reader.TokenType == JsonToken.StartArray)
                reader.Read();

            for (int i = 0; i < capacity; i++)
            {
                var item = new Guid(Convert.ToString(reader.Value));
                listOfT.Add(item);
                reader.Read();
            }

            if (reader.TokenType == JsonToken.EndArray)
                reader.Read();

            if (reader.TokenType == JsonToken.EndObject)
                reader.Read();

            return listOfT;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var listOfT = (List<Guid>)value;

            writer.WriteStartObject();

            writer.WritePropertyName(CapacityPropertyName);
            writer.WriteValue(listOfT.Count);

            writer.WritePropertyName(ListPropertyName);
            writer.WriteStartArray();

            foreach (var item in listOfT)
                writer.WriteValue(item);

            writer.WriteEndArray();

            writer.WriteEndObject();
        }
    }
}

在實現JsonConverter時很容易使閱讀器邏輯出錯。 您很可能在該行的某處讀取了太多次,這在以后會拋棄串行器。 我建議不要采用其他方法,而是嘗試在轉換器內部使用更高級別的LINQ-to-JSON API(JObjects),然后讓它與讀者打交道,而不是試圖弄清它的出路。 您的代碼將更短,更易理解/可維護。

這是使用LINQ-to-JSON的轉換器的替代實現。 它通過了所有測試。

public class ListofGuidJsonConverter : JsonConverter
{
    private const string CapacityPropertyName = "c";
    private const string ListPropertyName = "l";

    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(List<Guid>));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = JObject.Load(reader);
        int capacity = obj[CapacityPropertyName].Value<int>();
        List<Guid> list = new List<Guid>(capacity);
        foreach (JToken token in obj[ListPropertyName].Children())
        {
            list.Add(new Guid(token.ToString()));
        }
        return list;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        List<Guid> list = (List<Guid>)value;
        JObject obj = new JObject();
        obj.Add(CapacityPropertyName, list.Count);
        JArray array = new JArray();
        foreach (Guid guid in list)
        {
            array.Add(guid.ToString());
        }
        obj.Add(ListPropertyName, array);
        obj.WriteTo(writer);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM