加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 22:12:15 所属栏目:百科 来源:网络整理
导读:我需要使用Json.NET序列化许多不同的对象.我真的无法控制所提供的对象,所以我通常使用 TypeNameHandling.All进行序列化和反序列化. 但是,其中一些对象无法反序列化.具体来说,我得到一些System.Reflection.RuntimePropertyInfo类型.我想以标准化的方式处理这
我需要使用Json.NET序列化许多不同的对象.我真的无法控制所提供的对象,所以我通常使用 TypeNameHandling.All进行序列化和反序列化.

但是,其中一些对象无法反序列化.具体来说,我得到一些System.Reflection.RuntimePropertyInfo类型.我想以标准化的方式处理这些问题,因为我不知道反序列化时的目标类型.只要输出对象类型正确,我也不在乎.

我已尝试将CustomCreationConverter类型转换为在JsonSerializerSettings中定义的PropertyInfo.但是,即使CanConvert()返回true,也不会使用CustomCreationConverter的ReadJson().

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

ISerializable type ‘System.Reflection.RuntimePropertyInfo’ does not
have a valid constructor. To correctly implement ISerializable a
constructor that takes SerializationInfo and StreamingContext
parameters should be present.

我需要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,//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,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();
}

}

注意,为了强制deserialize方法使用自定义转换器,你应该像这样调用它的泛型版本:

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

在你的例子中也是如此,这就是为什么你没有达到你的断点.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读