JSON中属性的序列化.. NET抛出异常



下面是一个示例应用程序,它显示了使用JsonConverter对List进行自定义序列化。我注册一个自定义JsonSerializerSettings与JsonConvert。这些设置已经安装了ListOfGuidConverter。

当您将List作为序列化的根对象进行序列化和反序列化时,这非常有效。只要你有一个不同的根对象并且List是一个JSON属性。Net抛出异常,表示意外结束。

我能做些什么来解决这个问题?

谢谢丰富

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);
    }
}

最新更新