如何使用NewtonSoft JsonConverterAttribute和JToken.FromObject而不递归调用JsonConverter

问题描述

我从this example那里获取代码,并做了一些改动:

  1. 删除自定义构造函数,并对CanConvert类型进行硬编码。
  2. 将转换器从呼叫JsonConvert.SerializeObject()JsonConvert.DeserializeObject()中移除
  3. 为员工类型添加了JsonConverter属性

所以我最终使用了这个控制台应用程序:

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

namespace Testapp
{
    class Program
    {
        static void Main(string[] args)
        {
            Employee employee = new Employee
            {
                FirstName = "James",Roles = new List<string> {"Admin"}
            };

            string json = JsonConvert.SerializeObject(employee,Formatting.Indented);

            Console.WriteLine(json);

            Employee newEmployee = JsonConvert.DeserializeObject<Employee>(json);

            Console.WriteLine(newEmployee.FirstName);
        }
    }

    [JsonConverter(typeof(KeysJsonConverter))]
    public class Employee
    {
        public string        FirstName { get; set; }
        public IList<string> Roles     { get; set; }
    }

    public class KeysJsonConverter : JsonConverter
    {
        public override void WriteJson(JsonWriter writer,object value,JsonSerializer serializer)
        {
            JToken t = JToken.FromObject(value);

            if (t.Type != JTokenType.Object)
            {
                t.Writeto(writer);
            }
            else
            {
                JObject o = (JObject)t;
                IList<string> propertyNames = o.Properties().Select(p => p.Name).ToList();

                o.AddFirst(new JProperty("Keys",new JArray(propertyNames)));

                o.Writeto(writer);
            }
        }

        public override object ReadJson(JsonReader reader,Type objectType,object existingValue,JsonSerializer serializer)
        {
            throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
        }

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

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

不幸的是,在序列化和反序列化时使用属性而不是显式指定转换器会产生副作用: 现在,分配JToken t = JToken.FromObject(value);导致WriteJson()递归调用,从而导致堆栈溢出!

使用属性而不是在序列化/反序列化的任何地方指定转换器真的很好。

我试图在序列化/反序列化接口时添加一些通用类型信息,并且我想在很大程度上重用序列化的认行为。是否有其他方法可以执行而不调用JToken.FromObject()或其他会导致递归循环的事情?

已经尝试在base.WriteJson()调用JsonConverter,但这是一种抽象方法

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)