如何使用Json对PropertyInfo进行一般反序列化.NET



我需要用Json序列化许多不同的对象。NET。我真的无法控制所提供的对象,所以我通常使用TypeNameHandling进行序列化和反序列化。全部的

但是,其中一些对象无法反序列化。具体来说,我得到了一些系统。反射RuntimePropertyInfo类型。我希望以标准化的方式处理这些,因为在反序列化时我不知道目标类型。我也不在乎,只要输出对象类型是正确的。

我已尝试将CustomCreationConverter类型化为在JsonSerializerSettings中定义的PropertyInfo。然而,即使CanConvert()返回true,CustomCreationConverter的ReadJson()也从未被使用。

最终的结果就像我从未使用过CustomCreationConverter:一样

ISerializable类型"系统。反射RuntimePropertyInfo"不具有有效的构造函数。要正确实现ISerializable接受SerializationInfo和StreamingContext的构造函数参数应该存在。

我需要CustomCreationConverter来处理ReadJson,这样我就可以自己手动搜索PropertyInfo。

经过进一步调查,我添加到JsonSerializerSettings的转换器似乎根本没有被使用。如果我使用包括JsonConverter的Type和集合的DeserializeObject重载,则会使用Converter。我不确定提供给JsonSerializerSettings的转换器用于什么,但我希望它们在这种情况下能按我的意愿工作

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Formatters;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace Json
{
    class Program
    {
        static void Main(string[] args)
        {
            var jsonSerializerSettings = new JsonSerializerSettings()
            {
                TypeNameHandling = TypeNameHandling.All,
                TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple,
                Converters = new JsonConverter[] { new PropertyInfoConverter(), },
            };
            var propertyInfo = typeof(Test).GetProperty("Name");
            var serialized = JsonConvert.SerializeObject(propertyInfo, jsonSerializerSettings);
            var deserialized = JsonConvert.DeserializeObject(serialized, jsonSerializerSettings);
        }
    }
    public class Test
    {
        public string Name { get; set; }
    }
    public class PropertyInfoConverter : CustomCreationConverter<PropertyInfo>
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(PropertyInfo).IsAssignableFrom(objectType);
        }
        public override PropertyInfo Create(Type objectType)
        {
            return null;
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            return null; // This is never invoked, but is where I would attempt to find the PropertyInfo via Reflection searching.
        }
    }
}

假设您需要符合API,必须输入/输出PropertyInfo对象,则可以剪切转换器并使用新类仅保存重新创建对象所需的信息。

private class PropertyInfoData
{
    public string TypeName
    {
        get;
        set;
    }
    public string PropertyName
    {
        get;
        set;
    }
    public static PropertyInfoData FromProperty(PropertyInfo p)
    {
        return new PropertyInfoData()
        {
            TypeName = p.DeclaringType.AssemblyQualifiedName,
            PropertyName = p.Name,
        };
    }
    public PropertyInfo ToProperty()
    {
        return Type.GetType(this.TypeName).GetProperty(this.PropertyName);
    }
}

然后你可以像这样对它进行反序列化:

var jsonSerializerSettings = new JsonSerializerSettings()
{
    TypeNameHandling = TypeNameHandling.All,
    TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple,
    //Converters = new JsonConverter[] { new PropertyInfoConverter(), },
};
var propertyInfo = typeof(Test).GetProperty("Name");
var serialized = JsonConvert.SerializeObject(PropertyInfoData.FromProperty(propertyInfo), jsonSerializerSettings);
var deserialized = ((PropertyInfoData)JsonConvert.DeserializeObject(serialized, jsonSerializerSettings)).ToProperty();

下面是一个使用转换器的非常粗糙的例子(读取方法不是很健壮):

public class PropertyInfoConverter : JsonConverter
{
public override bool CanWrite
{
    get
    {
        return false;
    }
}
public override bool CanConvert(Type objectType)
{
    return typeof(PropertyInfo).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    string propertyName = null;
    string assemblyName = null;
    string typeName = null;
    while (reader.Read())
    {
        if (reader.TokenType == JsonToken.PropertyName)
        {
            string value = reader.Value.ToString();
            switch (reader.Value.ToString())
            {
                case "Name":
                    if (reader.Read())
                    {
                        propertyName = reader.Value.ToString();
                    }
                    break;
                case "AssemblyName":
                    if (reader.Read())
                    {
                        assemblyName = reader.Value.ToString();
                    }
                    break;
                case "ClassName":
                    if (reader.Read())
                    {
                        typeName = reader.Value.ToString();
                    }
                    break;
            }
        }       
    }
    return Type.GetType(typeName + ", " + assemblyName).GetProperty(propertyName);
}
/// <inheritdoc />
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    // When the property "CanWrite" returns false this method is never expected to be called.
    throw new NotImplementedException();
}

}

注意,为了强制反序列化方法使用自定义转换器,您应该调用它的通用版本,如下所示:

var deserialized = JsonConvert.DeserializeObject<PropertyInfo>(serialized, jsonSerializerSettings);

在你的例子中也是如此,这就是为什么你没有达到突破点的原因。

相关内容

  • 没有找到相关文章

最新更新