自定义JsonConverter作为属性

时间:2017-02-13 10:53:18

标签: c# json.net

我试图弄清楚如何使用自定义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将是simular,但是使用JObject.FromObject(value);

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

1 个答案:

答案 0 :(得分: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());