- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
此示例代码:
var json = JsonConvert.SerializeObject(new XmlException("bla"));
var exception = JsonConvert.DeserializeObject<XmlException>(json);
at System.Xml.XmlException..ctor(SerializationInfo info, StreamingContext context)
at Void .ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)(Object[] )
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateISerializable(JsonReader reader, JsonISerializableContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value)
at TestJson.Program.Main(String[] args) in C:\Projects\TestJson\TestJson\Program.cs:line 21
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
最佳答案
问题
这里的基本问题是弱类型的 JSON 与 ISerializabe
之间的不兼容。 + SerializationInfo
最初设计用于 BinaryFormatter
其流是强类型的。 IE。 ISerializable
的实现有时期望序列化流包含序列化字段的完整类型信息。事实证明, XmlException
有一个这样的实现。
具体如下。当 Json.NET 去调用 serialization constructor对于 ISerializable
类型,它 constructs a SerializationInfo
并通过 JsonFormatterConverter
当 SerializationInfo.GetValue(String, Type)
时,应该处理从 JSON 数据转换为所需类型的工作叫做。现在,当找不到指定的值时,此方法会引发异常。而且,不幸的是,没有 SerializationInfo.TryGetValue()
方法,要求需要反序列化可选字段的类使用 GetEnumerator()
手动循环遍历属性.但此外,没有方法可以检索构造函数中设置的转换器,这意味着在需要时无法转换可选字段,因此必须使用精确的预期类型反序列化需求。
您可以在 reference source for the constructor of XmlException
中看到这一点:
protected XmlException(SerializationInfo info, StreamingContext context) : base(info, context) {
res = (string) info.GetValue("res" , typeof(string));
args = (string[])info.GetValue("args", typeof(string[]));
lineNumber = (int) info.GetValue("lineNumber", typeof(int));
linePosition = (int) info.GetValue("linePosition", typeof(int));
// deserialize optional members
sourceUri = string.Empty;
string version = null;
foreach ( SerializationEntry e in info ) {
switch ( e.Name ) {
case "sourceUri":
sourceUri = (string)e.Value;
break;
case "version":
version = (string)e.Value;
break;
}
}
e.Value
仍然是
JValue
不是
string
在这一点上,所以反序列化窒息。
JsonSerializerInternalReader.CreateISerializable()
中解决这个特定问题, 替换字符串值
JValue
构建其
SerializationInfo
时带有实际字符串的标记,然后重新转换为
JValue
在
JsonFormatterConverter
如果需要转换。但是,这不会解决此类问题。例如,当
int
由 Json.NET 往返,它变成了
long
, 如果没有转换就会抛出。当然还有
DateTime
字段将在不转换的情况下抛出。这也将是一个突破性的变化
ISerializable
以前手工制作以与 Json.NET 一起使用的类可能会中断。
JsonConverter
嵌入了
ISerializable
的完整类型信息类型。
BinaryFormatter
流在你的 JSON 中。
Exception
的序列化代码类最初设计为与
BinaryFormatter
兼容,所以这应该是相当可靠的:
public class BinaryConverter<T> : JsonConverter where T : ISerializable
{
class BinaryData
{
public byte[] binaryData { get; set; }
}
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var data = serializer.Deserialize<BinaryData>(reader);
if (data == null || data.binaryData == null)
return null;
return BinaryFormatterHelper.FromByteArray<T>(data.binaryData);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var data = new BinaryData { binaryData = BinaryFormatterHelper.ToByteArray(value) };
serializer.Serialize(writer, data);
}
}
public static class BinaryFormatterHelper
{
public static byte [] ToByteArray<T>(T obj)
{
using (var stream = new MemoryStream())
{
new BinaryFormatter().Serialize(stream, obj);
return stream.ToArray();
}
}
public static T FromByteArray<T>(byte[] data)
{
return FromByteArray<T>(data, null);
}
public static T FromByteArray<T>(byte[] data, BinaryFormatter formatter)
{
using (var stream = new MemoryStream(data))
{
formatter = (formatter ?? new BinaryFormatter());
var obj = formatter.Deserialize(stream);
if (obj is T)
return (T)obj;
return default(T);
}
}
}
var settings = new JsonSerializerSettings { Converters = new[] { new BinaryConverter<Exception>() } };
BinaryFormatter
在某些 .Net 版本中丢失。 BinaryFormatter
只能在完全信任的情况下使用。 TypeNameHandling
嵌入类型信息 .
JsonSerializer.TypeNameHandling
,Json.NET 还具有在序列化流中嵌入非原始类型的 .NET 类型信息的可选功能。到适当的值。将此功能与原始类型的包装器一起使用,可以创建
JsonConverter
封装
SerializationInfo
和
SerializationEntry
并包含所有已知的类型信息:
public class ISerializableConverter<T> : JsonConverter where T : ISerializable
{
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var oldTypeNameHandling = serializer.TypeNameHandling;
var oldAssemblyFormat = serializer.TypeNameAssemblyFormat;
try
{
if (serializer.TypeNameHandling == TypeNameHandling.None)
serializer.TypeNameHandling = TypeNameHandling.Auto;
else if (serializer.TypeNameHandling == TypeNameHandling.Arrays)
serializer.TypeNameHandling = TypeNameHandling.All;
var data = serializer.Deserialize<SerializableData>(reader);
var type = data.ObjectType;
var info = new SerializationInfo(type, new FormatterConverter());
foreach (var item in data.Values)
info.AddValue(item.Key, item.Value.ObjectValue, item.Value.ObjectType);
var value = Activator.CreateInstance(type, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { info, serializer.Context }, serializer.Culture);
if (value is IObjectReference)
value = ((IObjectReference)value).GetRealObject(serializer.Context);
return value;
}
finally
{
serializer.TypeNameHandling = oldTypeNameHandling;
serializer.TypeNameAssemblyFormat = oldAssemblyFormat;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var oldTypeNameHandling = serializer.TypeNameHandling;
var oldAssemblyFormat = serializer.TypeNameAssemblyFormat;
try
{
var serializable = (ISerializable)value;
var context = serializer.Context;
var info = new SerializationInfo(value.GetType(), new FormatterConverter());
serializable.GetObjectData(info, context);
var data = SerializableData.CreateData(info, value.GetType());
if (serializer.TypeNameHandling == TypeNameHandling.None)
serializer.TypeNameHandling = TypeNameHandling.Auto;
else if (serializer.TypeNameHandling == TypeNameHandling.Arrays)
serializer.TypeNameHandling = TypeNameHandling.All;
// The following seems to be required by https://github.com/JamesNK/Newtonsoft.Json/issues/787
serializer.TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full;
serializer.Serialize(writer, data, typeof(SerializableData));
}
finally
{
serializer.TypeNameHandling = oldTypeNameHandling;
serializer.TypeNameAssemblyFormat = oldAssemblyFormat;
}
}
}
abstract class SerializableValue
{
[JsonIgnore]
public abstract object ObjectValue { get; }
[JsonIgnore]
public abstract Type ObjectType { get; }
public static SerializableValue CreateValue(SerializationEntry entry)
{
return CreateValue(entry.ObjectType, entry.Value);
}
public static SerializableValue CreateValue(Type type, object value)
{
if (value == null)
{
if (type == null)
throw new ArgumentException("type and value are both null");
return (SerializableValue)Activator.CreateInstance(typeof(SerializableValue<>).MakeGenericType(type));
}
else
{
type = value.GetType(); // Use most derived type
return (SerializableValue)Activator.CreateInstance(typeof(SerializableValue<>).MakeGenericType(type), value);
}
}
}
sealed class SerializableValue<T> : SerializableValue
{
public SerializableValue() : base() { }
public SerializableValue(T value)
: base()
{
this.Value = value;
}
public override object ObjectValue { get { return Value; } }
public override Type ObjectType { get { return typeof(T); } }
[JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)]
public T Value { get; private set; }
}
abstract class SerializableData
{
public SerializableData()
{
this.Values = new Dictionary<string, SerializableValue>();
}
public SerializableData(IEnumerable<SerializationEntry> values)
{
this.Values = values.ToDictionary(v => v.Name, v => SerializableValue.CreateValue(v));
}
[JsonProperty("values", ItemTypeNameHandling = TypeNameHandling.Auto)]
public Dictionary<string, SerializableValue> Values { get; private set; }
[JsonIgnore]
public abstract Type ObjectType { get; }
public static SerializableData CreateData(SerializationInfo info, Type initialType)
{
if (info == null)
throw new ArgumentNullException("info");
var type = info.GetSavedType(initialType);
if (type == null)
throw new InvalidOperationException("type == null");
return (SerializableData)Activator.CreateInstance(typeof(SerializableData<>).MakeGenericType(type), info.AsEnumerable());
}
}
sealed class SerializableData<T> : SerializableData
{
public SerializableData() : base() { }
public SerializableData(IEnumerable<SerializationEntry> values) : base(values) { }
public override Type ObjectType { get { return typeof(T); } }
}
public static class SerializationInfoExtensions
{
public static IEnumerable<SerializationEntry> AsEnumerable(this SerializationInfo info)
{
if (info == null)
throw new NullReferenceException();
var enumerator = info.GetEnumerator();
while (enumerator.MoveNext())
{
yield return enumerator.Current;
}
}
public static Type GetSavedType(this SerializationInfo info, Type initialType)
{
if (initialType != null)
{
if (info.FullTypeName == initialType.FullName
&& info.AssemblyName == initialType.Module.Assembly.FullName)
return initialType;
}
var assembly = Assembly.Load(info.AssemblyName);
if (assembly != null)
{
var type = assembly.GetType(info.FullTypeName);
if (type != null)
return type;
}
return initialType;
}
}
{
"$type": "Question35015357.SerializableData`1[[System.Xml.XmlException, System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"values": {
"ClassName": {
"$type": "Question35015357.SerializableValue`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"value": "System.Xml.XmlException"
},
"Message": {
"$type": "Question35015357.SerializableValue`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"value": "bla"
},
"Data": {
"$type": "Question35015357.SerializableValue`1[[System.Collections.IDictionary, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
},
"InnerException": {
"$type": "Question35015357.SerializableValue`1[[System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
},
"HelpURL": {
"$type": "Question35015357.SerializableValue`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
},
"StackTraceString": {
"$type": "Question35015357.SerializableValue`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
},
"RemoteStackTraceString": {
"$type": "Question35015357.SerializableValue`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
},
"RemoteStackIndex": {
"$type": "Question35015357.SerializableValue`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"value": 0
},
"ExceptionMethod": {
"$type": "Question35015357.SerializableValue`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
},
"HResult": {
"$type": "Question35015357.SerializableValue`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"value": -2146232000
},
"Source": {
"$type": "Question35015357.SerializableValue`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
},
"res": {
"$type": "Question35015357.SerializableValue`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"value": "Xml_UserException"
},
"args": {
"$type": "Question35015357.SerializableValue`1[[System.String[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"value": [
"bla"
]
},
"lineNumber": {
"$type": "Question35015357.SerializableValue`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"value": 0
},
"linePosition": {
"$type": "Question35015357.SerializableValue`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"value": 0
},
"sourceUri": {
"$type": "Question35015357.SerializableValue`1[[System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
},
"version": {
"$type": "Question35015357.SerializableValue`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Tile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"value": "2.0"
}
}
}
SerializationBinder
进一步减少安全隐患只加载预期类型,如
TypeNameHandling caution in Newtonsoft Json 中所述.
JsonSerializerInternalReader.CreateISerializable()
投入部分信任:
private object CreateISerializable(JsonReader reader, JsonISerializableContract contract, JsonProperty member, string id)
{
Type objectType = contract.UnderlyingType;
if (!JsonTypeReflector.FullyTrusted)
{
string message = @"Type '{0}' implements ISerializable but cannot be deserialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine +
@"To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true." + Environment.NewLine;
message = message.FormatWith(CultureInfo.InvariantCulture, objectType);
throw JsonSerializationException.Create(reader, message);
}
关于c# - 如何使用 Newtonsoft JSON(反)序列化 XmlException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35015357/
我在谷歌上花了很长时间,所以如果这是一个简单的修复请原谅我,但我找不到任何与 C# 中这个特定问题的修复相关的内容。 当尝试使用以下代码时,出现此错误: string obj = JsonConver
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 去年关闭。 Improve this
我正在尝试重新创建这个 json: { "request": { " TestRequest": { "OrderID": {
我正在测试我的 Web API。模拟数据我有这个: var objs = ((JArray)JsonConvert.DeserializeObject("{ \"PrintId\":10,\"Head
目前正在尝试使用 fixer.io API 在 C# 中创建货币转换。 我在从 Twitter API 解析 JSON 时使用了与下面类似的方法,并且没有任何问题,我不完全确定这里发生了什么。 API
我正在尝试建立 Mike Jansen 的 JIRA REST Client ,我正在尝试提取 JIRA 版本信息。我是 JSON 的新手,所以我不确定这只是格式问题还是什么。 调试时,我有以下标记:
我正在尝试使用 将对象动态序列化到即时窗口中 Newtonsoft.Json.JsonConvert.SerializeObject(myObj); 但是我得到以下错误 The type 'Newto
我无法在 Visual Studio 2013 中构建解决方案。 这发生在我将我的 JSON.NET 包更新到 6.0.1 之后。在此之前,它就像一个魅力。 有什么想法吗? PS:这可能是关于 OWI
当有如下代码时 var TermSource = token.Value("annotations") .Values("Term Source") .FirstOrDefault
我需要将选中的复选框代码从 JavaScript 传递给 C#。我能够通过 JSON 发送代码。我的 JSON 值以 JArray 的形式出现。我在标题中得到了异常(exception)。 JSON:
注意:解决重定向问题后,我遇到了另一个问题,即出现错误“无法将 Newtonsoft.Json.Linq.JArray 转换为 Newtonsoft.Json.Linq.JToken”。因此,在我的回
我有以下简单的 POCO: public class ApiKey { public ApiKey(string key, string owner, List claims = nu
我查过这个问题,但我没有看到太多答案,显然没有一个有帮助,否则我不会问。我是 .NET 新手。 我的本地环境是Win7,Microsoft Virtual Web Developer 2010 Exp
好的-我已经将这个问题打了几个小时。是时候寻求帮助了。 我刚刚将Web应用程序项目升级到ASP.NET MVC 4 RC和新的WebApi。 我的Web api方法现在返回EMPTY json“{}”
我想忽略类中的某些属性,但出于多种原因我想保留类 POCO。因此我不想引入对 Json.NET 的依赖,也不想使用 JsonIgnoreAttribute。 有没有办法自定义契约(Contract)解
我正在尝试修复我编写的 WinForms 程序中的错误;我正在解析一个 JSON 字符串,然后将一些结果放入各种变量中。 有时,JSON 的特定元素不存在(出于真正的原因),因此我尝试使用以下代码来处
我只是尝试使用 C# 中的 Newtonsoft JSON 库将文件中的一些 JSON 反序列化为对象列表。以下是 MeetingFile.txt 文件的内容: [ { "People":
这是一个非常奇怪的错误发生。我有这些对象: public class Mobile_SettingModels { public string Token { get; set; }
我粘贴了 http://www.codeproject.com/Tips/789481/Bridging-the-Gap-between-Linqpad-and-Visual-Studio 中的代码进
这个问题在这里已经有了答案: Can I optionally turn off the JsonIgnore attribute at runtime? (3 个答案) 关闭 4 年前。 我目前正
我是一名优秀的程序员,十分优秀!