在下面的代码中,我使用Json.Net序列化一个对象。这个Json嵌入了类型名。然后,我更改其中一个类型名称以导致错误(这是一个测试,我正在处理现有项目中的一个实际问题)。当我反序列化Json时,我希望得到一个对象,该对象对于带有篡改类型名称的属性具有一个空值。相反,序列化程序退出并返回null。我的期望正确吗?我是否可以以某种方式更改设置,以便为根对象获得一个非空对象?请注意,我得到的第二个错误表明序列化程序中存在一个错误。
static public class JsonTest
{
static public void Test()
{
// Create test object
A a = new A
{
MyTest = new MyTest(),
};
// Serialize it.
string json = JsonConvert.SerializeObject(a, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
// Fiddle class name to induce error
json = json.Replace("+MyTest", "+MyTest2");
// Before: {"MyTest":{"$type":"<Namespace>.JsonTest+MyTest, <Assembly>"}}
// After: {"MyTest":{"$type":"<Namespace>.JsonTest+MyTest2, <Assembly>"}}
// Deserialize
A a2 = JsonConvert.DeserializeObject<A>(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
Error = (object sender, ErrorEventArgs e) =>
{
e.ErrorContext.Handled = true; // Should have only one error: the unrecognized Type
}
});
// A second error occurs: Error = {Newtonsoft.Json.JsonSerializationException: Additional text found in JSON string after finishing deserializing object....
// a2 is null
}
public class A
{
public ITest MyTest { get; set; }
}
public interface ITest { }
public class MyTest : ITest { }
}
发布于 2017-03-29 20:20:46
更新
此问题已在Json.NET 10.0.2 in 本意见书中修复。
原始答案
这看起来是Json.NET中的一个bug。如果我设置了JsonSerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead
,那么问题就消失了:
// Deserialize
A a2 = JsonConvert.DeserializeObject<A>(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead,
Error = (object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e) =>
{
Debug.WriteLine(e.ErrorContext.Path);
e.ErrorContext.Handled = true; // Should have only one error: the unrecognized Type
}
});
Debug.Assert(a2 != null); // No assert.
但是,不需要打开此设置,它允许读取元数据属性,包括位于JSON对象中任何位置的"$type"
,而不仅仅是作为第一个属性。最有可能的是,它巧合地修复了bug,因为它需要在开始反序列化之前预先加载整个JSON对象。
如果你想的话,你可以报告问题。
稍微调试一下,问题似乎是,由于无法构造内部MyTest
对象,JsonSerializerInternalReader.PopulateObject()
在填充外部对象A
时捕获和处理异常。正因为如此,JsonReader
没有经过内部嵌套的对象,使读取器和序列化程序处于不一致的状态。这说明了第二个异常和最终的Additional text found in JSON string after finishing deserializing object. Path ''
异常。
https://stackoverflow.com/questions/43104683
复制相似问题