c# – JSON.NET,如果预期的对象无法反序列化,则实例化回退对象

我有一个项目树,我正在尝试使用 JSON.NET反序列化.有些情况(例如重命名节点类型)可能会导致树上的节点无法反序列化.

在这些情况下,我想插入一个节点的默认实例(可能是其他类型)来代替未反序列化的对象.

这样,我的用户仍然可以加载他们的保存文件,获得他们必须修复的“空”节点……但是,至少他们仍然可以加载他们的文件!

我一直在做一些研究,并且有一些事情要尝试使用SerializationBinder和/或在序列化程序的回调中破解一些错误处理,但我觉得有点问,如果有一些明显的解决方案我缺少,或输入有关这些方法.

如果它很重要,这是一个快速发展的内部工具,我们偶尔会想到一些破碎的树木,我们真的希望它们会加载,无论如何:)

谢谢!

最佳答案 我想出了一些东西,非常感谢这里的其他几十个帖子!

用JsonConverter修饰的节点基类

[JsonObject( IsReference = true, TypeNameHandling = TypeNameHandling.All )]
[JsonConverter( typeof( ChainNodeConverter ))]
public abstract class Node
{
    public List< Node > Children { get; set; }
}

ErrorNode类具有一些属性来帮助id /恢复失败的节点

public class ErrorNode : Node
{
    public JToken JToken { get; set; }
    public string FailedTypeString { get; set; }
}

NodeConverer类

public class NodeConverter : JsonConverter
{
    public override bool CanRead { get { return true; } }

    public override bool CanWrite { get { return false; } }

    public override bool CanConvert( Type objectType ) { return typeof( Node ).IsAssignableFrom( objectType ); }


    public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer )
    {
        throw new NotImplementedException("If CanWrite is false; this won't be called.");
    }


    public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
    {
        var jToken = JToken.ReadFrom( reader );

        var refString = jToken.Value< string >( "$ref" );
        var firstReference = refString == null;

        if ( firstReference )
        {
            var typeString = jToken.Value<string>( "$type" );

            if ( typeString != null )
            {
                var type = Type.GetType( typeString );

                if ( type == null )
                {
                    var errorNode = new ErrorNode();

                    errorNode.JToken = jToken;
                    errorNode.FailedTypeString = typeString;

                    // Apply the old node's relationships to errorNode
                    serializer.Populate( jToken.CreateReader(), errorNode );

                    return errorNode;
                }
            }
        }

        // Default-like behaviour
        return serializer.Deserialize( jToken.CreateReader() );
    }
}
点赞