如何将参数传递给构造函数反序列化json [英] How to pass parameter to constructor deserializing json

查看:92
本文介绍了如何将参数传递给构造函数反序列化json的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Newtonsoft.Json反序列化对象时,将一些父实例传递给构造函数时,我遇到了一个小问题.

I have a small problem with passing some parent instance to a constructor when deserializing an object with Newtonsoft.Json.

假设我有以下课程

public class A
{
    public string Str1 { get; set; }

    public IList<B> Bs { get; set; }
}

public class B
{
    public B(A a)
    {
        // a should not be null!
        Console.WriteLine(a.Str)
    }
}

现在我像这样反序列化对象a:

And now i serailze and than deserialize the object a like this:

A a = new A()
a.Bs = new List<B>()
a.Bs.Add(new B(a));
a.Bs.Add(new B(a));
a.Bs.Add(new B(a));

var json = JsonConvert.SerializeObject(a);

// Here i need to call the constructor of B when creating new instances
var newA = JsonConvert.DeserializeObject<A>(json);

问题是,当反序列化对象时,null将传递给B的构造函数.以前有没有人解决过这个问题/问题?

The problem is, that when deserializing the object, null will be passed to the constructor of B. Does any one has solved this issue/problem before?

非常感谢!

推荐答案

在您的问题和评论中,您说过B类对A没有任何公共属性.因此,当您序列化B时,不会将任何A写入JSON,因为Json.Net默认仅序列化公共信息.因此,在反序列化时,将没有足够的信息来重新创建B,因为JSON中没有A.因此,第一步是使Json.Net看到BA的引用.如果您不想公开它,那很好,但是您至少需要用[JsonProperty]属性标记该成员,以允许Json.Net看到"它.

In your question and comments you've said that the class B does not have any public property for A. So, when you serialize B, then no A will be written to the JSON, because Json.Net only serializes the public information by default. Therefore, when deserializing, there will not be enough information to recreate B, because there is no A in the JSON. So, step one is making B's reference to A visible to Json.Net. If you don't want to make it public, that is fine, but you will at least need to mark the member with a [JsonProperty] attribute to allow Json.Net to "see" it.

public class B
{
    [JsonProperty]
    private A a;

    public B(A a)
    {
        this.a = a;  // be sure to set the A member in your constructor
    }
}

现在,如果执行上述操作,您将遇到第二个问题:您的类结构有一个引用循环(A有一个B的列表,每个列表都引用回A),并且序列化程序将在这种情况下,默认情况下引发异常.解决方案是将序列化程序的 PreserveReferencesHandling 设置设置为Objects(默认为None).这不仅将允许序列化程序在序列化期间处理引用循环,而且还将在反序列化期间保留原始引用,以便所有B都引用相同的A实例. (这是通过写入JSON的特殊$id$ref属性来完成的.)

Now if you do the above you will run into a second problem: your class structure has a reference loop (A has a list of Bs which each refer back to A), and the serializer will throw an exception by default in this case. The solution is to set the serializer's PreserveReferencesHandling setting to Objects (the default is None). This will not only allow the serializer to handle the reference loops during serialization, but will also preserve the original references during deserialization, so that all the Bs will refer to the same A instance. (This is accomplished via special $id and $ref properties that are written into the JSON.)

JsonSerializerSettings settings = new JsonSerializerSettings
{
    PreserveReferencesHandling = PreserveReferencesHandling.Objects,
};

var json = JsonConvert.SerializeObject(a, settings);

var newA = JsonConvert.DeserializeObject<A>(json, settings);

工作示例: https://dotnetfiddle.net/N0FUID

这篇关于如何将参数传递给构造函数反序列化json的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆