【问题标题】:Custom JsonConverter as Attribute自定义 JsonConverter 作为属性
【发布时间】:2017-02-13 19:49:46
【问题描述】:

我想弄清楚如何使用自定义 JsonConverter 作为属性。问题是我无法弄清楚如何在转换器中获取 FOO 对象。

例子

[Newtonsoft.Json.JsonConverter(typeof(FOOConverter))]
public interface IFOO
{
    ...
}


public class FOOConverter : Newtonsoft.Json.JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jobj = serializer.Deserialize<JObject>(reader);
        ...
        var foo = jobj.ToObject<IFOO>() // Calls the converter again?
    }
}

.ToObject() 将再次运行转换器并导致堆栈溢出,这是有道理的,因为它查看属性,但我怎样才能获得 IFOO 对象呢?

编辑:WriteJson 将是类似的,但带有 JObject.FromObject(value);

使用需要灵活,例如:某些属性可能在序列化期间被加密/加密,其他时候,可能有需要缓存的属性值。想几个用例。

【问题讨论】:

    标签: c# json.net


    【解决方案1】:

    JSON 类:

    [KnownType(typeof(B))]
    public class A
    {
       public string Name { get; set; }
    }
    
    public class B : A
    {
       public string LastName { get; set; }
    }
    

    转换器代码:

        public  class KnownTypeConverter : JsonConverter
        {
            public override bool CanConvert(Type objectType)
            {
                return System.Attribute.GetCustomAttributes(objectType).Any(v => v is KnownTypeAttribute);
            }
    
            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                // Load JObject from stream
                JObject jObject = JObject.Load(reader);
    
                // Create target object based on JObject
                System.Attribute[] attrs = System.Attribute.GetCustomAttributes(objectType);  // Reflection. 
    
                    // Displaying output. 
                foreach (System.Attribute attr in attrs)
                {
                    if (attr is KnownTypeAttribute)
                    {
                        KnownTypeAttribute k = (KnownTypeAttribute) attr;
                        var props = k.Type.GetProperties();
                        bool found = true;
                        foreach (var f in jObject)
                        {
                            if (!props.Any(z => z.Name == f.Key))
                            {
                                found = false;
                                break;
                            }
                        }
    
                        if (found)
                        {
                            var target = Activator.CreateInstance(k.Type);
                            serializer.Populate(jObject.CreateReader(),target);
                            return target;
                        }
                    }
                }
                throw new ObjectNotFoundException();
    
    
                // Populate the object properties
    
            }
    
            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                throw new NotImplementedException();
            }
        }
    

    用法:

    var ret  = JsonConvert.DeserializeObject<A>(json, new KnownTypeConverter());
    

    【讨论】:

    • 感谢您的想法,Activator.CreateInstance 的问题是在 WriteJson 中我还需要需要使用 JObject.FromObject 转换的 IFoo 对象。 FromObject 和 ToObject 一样
    猜你喜欢
    • 2017-09-08
    • 2020-01-22
    • 1970-01-01
    • 2019-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-25
    相关资源
    最近更新 更多