【发布时间】:2021-08-04 08:21:01
【问题描述】:
我必须使用 DataContractSerializer 序列化 Newtonsoft JObject,它会因堆栈溢出而崩溃。 如何让它发挥作用? 我的代码是。
var serializer = new DataContractSerializer(typeof(JObject));
MemoryStream stream1 = new MemoryStream();
var writer = XmlDictionaryWriter.CreateBinaryWriter(stream1);
var obj = new JObject();
serializer.WriteObject(writer, obj);
writer.Flush();
以下示例使用ISerializationSurrogateProvider 功能将JObject 转换为通用类型。它会因堆栈溢出而崩溃。
using System;
using System.IO;
using Newtonsoft.Json.Linq;
using System.Runtime.Serialization;
using System.Xml;
class Program
{
[DataContract(Name = "JTokenReference", Namespace = "urn:actors")]
[Serializable]
public sealed class JTokenReference
{
public JTokenReference()
{
}
[DataMember(Name = "JType", Order = 0, IsRequired = true)]
public JTokenType JType { get; set; }
[DataMember(Name = "Value", Order = 1, IsRequired = true)]
public string Value { get; set; }
public static JTokenReference From(JToken jt)
{
if (jt == null)
{
return null;
}
return new JTokenReference()
{
Value = jt.ToString(),
JType = jt.Type
};
}
public object To()
{
switch (JType)
{
case JTokenType.Object:
{
return JObject.Parse(Value);
}
case JTokenType.Array:
{
return JArray.Parse(Value);
}
default:
{
return JToken.Parse(Value);
}
}
}
}
internal class ActorDataContractSurrogate : ISerializationSurrogateProvider
{
public static readonly ISerializationSurrogateProvider Instance = new ActorDataContractSurrogate();
public Type GetSurrogateType(Type type)
{
if (typeof(JToken).IsAssignableFrom(type))
{
return typeof(JTokenReference);
}
return type;
}
public object GetObjectToSerialize(object obj, Type targetType)
{
if (obj == null)
{
return null;
}
else if (obj is JToken jt)
{
return JTokenReference.From(jt);
}
return obj;
}
public object GetDeserializedObject(object obj, Type targetType)
{
if (obj == null)
{
return null;
}
else if (obj is JTokenReference reference &&
typeof(JToken).IsAssignableFrom(targetType))
{
return reference.To();
}
return obj;
}
}
[DataContract(Name = "Test", Namespace = "urn:actors")]
[Serializable]
public class Test
{
[DataMember(Name = "obj", Order = 0, IsRequired = false)]
public JObject obj;
}
static void Main(string[] args)
{
var serializer = new DataContractSerializer(typeof(Test),
new DataContractSerializerSettings()
{
MaxItemsInObjectGraph = int.MaxValue,
KnownTypes = new Type[] { typeof(JTokenReference), typeof(JObject), typeof(JToken) },
});
serializer.SetSerializationSurrogateProvider(ActorDataContractSurrogate.Instance);
MemoryStream stream1 = new MemoryStream();
var writer = XmlDictionaryWriter.CreateBinaryWriter(stream1);
var obj = new JObject();
var test = new Test()
{
obj = obj,
};
serializer.WriteObject(writer, test);
writer.Flush();
Console.WriteLine(System.Text.Encoding.UTF8.GetString(stream1.GetBuffer(), 0, checked((int)stream1.Length)));
}
}
我正在尝试定义一个新类型 JTokenReference 来在序列化时替换 JObject/JToken,但它在替换发生之前就崩溃了。似乎无法解析类型。
【问题讨论】:
-
我建议您首先使用this answer 将
JObject转换为标准的.NET 类型,然后您可以使用DataContractSerializer序列化该结果。 -
你为什么要用
DataContractSerializer序列化JObject?JObject是 Json.NET 的 JSON 文档对象模型,没有理由想象它可以被DataContractSerializer序列化为 XML。如果您只需要将 JSON 转换为 XML,请参阅 How to convert JSON to XML or XML to JSON?。如果您已经解析为JObject,您可以使用JsonExtension.ToXElement()from How to generate XML from JSON with parent node of array items 将其转换为 XML。 -
我使用 ISerializationSurrogateProvider 将其转换为 .NET 类型,但由于同样的原因它也崩溃了。
-
第3方框架将每个参数都转换为XML,不幸的是我的参数是一个json.net对象。我别无选择,那么如何解决这个问题?
-
ISerializationSurrogateProvider 将其转换为 .NET 类型,但由于同样的原因它也崩溃了。 - 那么您能否分享带有 JSON 和重现代码的 minimal reproducible example问题?另外,它是崩溃,还是异常?如果是后者,还请分享异常的完整
ToString()输出,包括异常类型、消息、回溯和内部异常(如果有)。
标签: c# json.net datacontractserializer