【发布时间】:2019-06-28 13:45:14
【问题描述】:
我正在尝试使用 Newtonsoft.Json 实现自定义序列化,我希望将所有字段序列化,然后反序列化为正确的类型。该类包含“object”类型的字段,实现ISerializable,具有[Serializable] 属性集,并具有序列化构造函数。我将此对象字段的值设置为某个类的实例,然后对其进行序列化。我使用JsonSerializer 并将TypeNameHandling 设置为TypeNameHandling.Auto。
这是我正在尝试的代码:
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.IO;
using System.Runtime.Serialization;
namespace ConsoleApp1
{
class Program
{
[Serializable]
class Foobar : ISerializable
{
public Foobar()
{
}
public Foobar(SerializationInfo info, StreamingContext context)
{
something = info.GetValue("something", typeof(object));
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("something", something);
}
public object Something { get { return something; } set { something = value; } }
private object something;
[JsonIgnore]
private string someOtherObject = "foobar";
}
class SomeOtherClass
{
public string Foo { get; set; }
public string Bar { get; set; }
}
static void Main(string[] args)
{
Foobar myObj = new Foobar();
myObj.Something = new SomeOtherClass() { Bar = "My first", Foo = "fqwkifjwq" };
var serializer = new Newtonsoft.Json.JsonSerializer();
serializer.TypeNameHandling = TypeNameHandling.Auto;
serializer.Formatting = Formatting.Indented;
string serialized;
using (var tw = new StringWriter())
{
using (var jw = new JsonTextWriter(tw))
serializer.Serialize(jw, myObj);
tw.Flush();
serialized = tw.ToString();
}
Foobar deserialized;
using (var rt = new StringReader(serialized))
using (var jsonReader = new JsonTextReader(rt))
deserialized = serializer.Deserialize<Foobar>(jsonReader);
Console.WriteLine("Type of deserialized.Something: " + deserialized.Something.GetType().FullName);
}
}
}
反序列化后,字段Foobar.Something 只是一个Newtonsoft.Json.Linq.JObject,这不是我想要的。我希望将其正确反序列化为SomeOtherClass 类型的对象。序列化的输出确实包含所需的信息:
{
"something": {
"$type": "ConsoleApp1.Program+SomeOtherClass, ConsoleApp1",
"Foo": "fqwkifjwq",
"Bar": "My first"
}
}
这是我迄今为止尝试过的:
- 使用上面的代码。完全按照我上面的描述进行。
- 在我正在序列化的对象上使用
[JsonObject(MemberSerialization = MemberSerialization.Fields)]属性。然后我在Foobar.Something字段(SomeOtherClass实例)上得到一个正确类型的对象,但是,任何具有默认值的非序列化字段都被初始化为 null 而不是它们的默认值(如字段Foobar.someOtherObject)。 - 删除
Serializable属性。那么ISerializable GetObjectData和序列化构造函数就不会被调用。 - 将 JsonSerializer 的
TypeNameHandling属性设置为All(无效)。
那么 - 关于如何解决这个问题的任何提示?
【问题讨论】:
-
默认情况下,Json.Net 将序列化所有公共属性。如果向字段添加 [JsonProperty] 属性,则可以使其序列化/反序列化特定的私有字段。看起来您没有在序列化构造函数或
GetObjectData中执行任何自定义操作,所以除非我遗漏了什么,否则我认为您不需要实现ISerializable也不需要使用[Serializable]属性。如果您只是将Foobar设为普通的 c# 对象,它似乎可以按预期工作。见dotnetfiddle.net/0e1uGM。我错过了什么吗? -
我的实际用例是序列化和反序列化一个相当庞大而复杂的数据结构,其中我需要序列化的不一定只是公开的。它是遗留代码,并且存在的字段和属性的数量使得将 [JsonPropery] 属性添加到我需要序列化的每个字段是不切实际的。将它们全部制作成适当的公共属性也是不切实际的。所以我想我会序列化所有字段(我通过在 GetObjectData/ctor 中的反射获取所有字段来做到这一点)。它可以工作 99%。但是,我的问题中的具体情况并非如此。
标签: c# types json.net json-serialization