如何将参数传递给构造函数反序列化json [英] How to pass parameter to constructor deserializing 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看到B
对A
的引用.如果您不想公开它,那很好,但是您至少需要用[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 B
s 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 B
s 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屋!