当前位置: 首页 > 面试题库 >

C#反序列化对象的派生并具有引用

鲜于允晨
2023-03-14
问题内容

我有一个类型节点的对象。 Node.cs

拨打电话时,序列化工作如下:

var nodeSer = JsonConvert.SerializeObject(mynode, Formatting.Indented,
   new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });

我的问题是以下调用不起作用。

var n = JsonConvert.DeserializeObject<Node>(nodeSer,
                new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects, TypeNameHandling = TypeNameHandling.Auto });

该调用导致以下错误:

Newtonsoft.Json.JsonSerializationException: "ISerializable type 'System.Action' does not have a valid constructor. To correctly implement ISerializable a constructor that takes SerializationInfo and StreamingContext parameters should be present. Path 'Size.ValueChanged', line 35, position 5."

我必须如何设计反序列化调用?


问题答案:

Json.NET不会序列化事件,因此存储库基本类型中的public event PropertyChangedEventHandler PropertyChangedin
(序列化)期间不应引起问题。PropertyChangedBaseHousePlan

但是,该存储库中的至少一种类型具有一个System.Action委托而不是一个值更改时要处理的事件,尤其是
BindablePoint

public class BindablePoint: PropertyChangedBase
{
    public double X
    {
        get { return Value.X; }
        set { Value = new Point(value,  Value.Y); }
    }

    public double  Y
    {
        get { return Value.Y; }
        set { Value = new Point( Value.X, value); }
    }

    private Point _value;
    public Point Value
    {
        get { return _value; }
        set
        {
            _value = value;
            OnPropertyChanged("Value");
            OnPropertyChanged("X");
            OnPropertyChanged("Y");

            if (ValueChanged != null)
                ValueChanged();
        }
    }

    // This property is causing problems for Json.NET
    public Action ValueChanged;
}

目前尚不清楚为什么为此目的使用委托而不是事件,但是System.ActionJson.NET不能反序列化。实际上,序列化和反序列化这些委托没有任何意义,因为它们在构造函数中分配给Node

public class Node: DiagramObject
{
    public Node()
    {
        Size.ValueChanged = RecalculateSnaps;
        Location.ValueChanged = RecalculateSnaps;
    }

一种简单的解决方案是用
[JsonIgnore]

    [JsonIgnore]
    public Action ValueChanged;

第二种简单的解决方案是用适当的事件替换委托,Json.NET现在将忽略该事件:

    public event EventHandler ValueChanged;

如果出于某种原因无法更改这些类型,则可以创建一个自定义ContractResolver,该自定义自动忽略所有委托类型属性:

public class IgnorePropertiesOfTypeContractResolver<T> : IgnorePropertiesOfTypeContractResolver
{
    // As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons.
    // http://www.newtonsoft.com/json/help/html/ContractResolver.htm
    // http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm
    // "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance."
    static IgnorePropertiesOfTypeContractResolver<T> instance;

    static IgnorePropertiesOfTypeContractResolver() { instance = new IgnorePropertiesOfTypeContractResolver<T>(); }

    public static IgnorePropertiesOfTypeContractResolver<T> Instance { get { return instance; } }

    public IgnorePropertiesOfTypeContractResolver() : base(new[] { typeof(T) }) { }
}

/// <summary>
/// Contract resolver to ignore properties of any number of given types.
/// </summary>
public class IgnorePropertiesOfTypeContractResolver : DefaultContractResolver
{
    readonly HashSet<Type> toIgnore;

    public IgnorePropertiesOfTypeContractResolver(IEnumerable<Type> toIgnore)
    {
        if (toIgnore == null)
            throw new ArgumentNullException();
        this.toIgnore = new HashSet<Type>(toIgnore);
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);

        if (property.PropertyType.BaseTypesAndSelf().Any(t => toIgnore.Contains(t)))
        {
            property.Ignored = true;
        }

        return property;
    }
}

public static class TypeExtensions
{
    public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
    {
        while (type != null)
        {
            yield return type;
            type = type.BaseType;
        }
    }
}

现在使用以下设置进行序列化:

var settings = new JsonSerializerSettings
{
    PreserveReferencesHandling = PreserveReferencesHandling.Objects,
    ContractResolver = IgnorePropertiesOfTypeContractResolver<System.Delegate>.Instance,
};

ValueChanged属性将不再被序列化或反序列化。



 类似资料:
  • 问题内容: 使用JSON定义的样子,为了将其反序列化为对象,我需要在我的类上创建一个名为“ event”的属性,这是一个C#关键字。还有另一种方法可以告诉它字段名称是什么? 这是JSON的示例: {event:123 data:{“ data”:“ 0D0401”,“ ttl”:“ 60”,“ published_at”:“ 2014-04-16T18:04:42.446Z”,“ id”:“ 48

  • 其中备注是对象内部的vavr列表字段。 现在,如果尝试将相同的值反序列化到对象中,则会出现错误: 当尝试反序列化时,为什么serified JSON文本不起作用? 在Java代码中有没有其他方法可以将vavr对象打印成文本格式并将其转换回POJO?

  • 我正在做一个小组项目,我们遇到了一个软件序列化部分的问题。我们有类协议: 我们还有SearchResult类: 当我们通过客户端-服务器套接字连接编写协议类时,就会出现问题。问题是Protocol类中的TableModel对象在序列化/反序列化过程中的某个时刻变为null,而我们所做的任何事情都还没有解决这个问题。 到目前为止,我们已尝试: -在SearchResult中实现Serializabl

  • 我试图将JSON字符串反序列化为Java对象,但遇到以下异常: JsonDeserializer com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter@306A30C7未能对给定类型类java.util.ArrayList的json对象[“93”]进行反序列化 我的主文件: 应该表示JSON的类是: 我尝试了SO上给出的解决方案,但也有

  • 问题内容: 我对反序列化json对象几乎没有问题。我的json来自http网址: 我下载的JSON的屏幕 我不知道如何反序列化以动态创建按钮。我想出了如何用文本创建按钮,但是我不知道如何使用它们所具有的选项来创建按钮。我尝试在Windows Form应用程序中获取这些选项进行测试,但应用程序将崩溃。谢谢你的帮助。 问题答案: 您的课程应类似于: 然后,您应该可以使用Newtonsoft.Json反

  • 我对反序列化json对象没有什么问题。我的json来自超文本传输协议url: 我下载的JSON的屏幕 我不知道如何反序列化以动态创建按钮。我知道如何使用文本创建按钮,但我不知道如何使用它们拥有的选项制作它们。我尝试在Windows表单应用程序中获取这些选项进行测试,但应用程序会崩溃。谢谢您的帮助。