如何转换具有递归类型的对象(不是对象,只是类型)?尝试使用父/子关系序列化对象时,以下代码失败。
错误是对 ser.WriteObject(stream1,parent)的最后一次调用; 会抛出异常:
System.Runtime.Serialization.SerializationException was unhandled
HResult=-2146233076
Message=Type 'TestJson.Child' with data contract name 'Child:http://schemas.datacontract.org/2004/07/TestJson' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
Source=System.Runtime.Serialization
StackTrace:
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.Json.XmlObjectSerializerWriteContextComplexJson.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContextComplex.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at WriteArrayOfPersonToJson(XmlWriterDelegator , Object , XmlObjectSerializerWriteContextComplexJson , CollectionDataContract )
at System.Runtime.Serialization.Json.JsonCollectionDataContract.WriteJsonValueCore(XmlWriterDelegator jsonWriter, Object obj, XmlObjectSerializerWriteContextComplexJson context, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.Json.XmlObjectSerializerWriteContextComplexJson.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContextComplex.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at WriteAdultToJson(XmlWriterDelegator , Object , XmlObjectSerializerWriteContextComplexJson , ClassDataContract , XmlDictionaryString[] )
at System.Runtime.Serialization.Json.JsonClassDataContract.WriteJsonValueCore(XmlWriterDelegator jsonWriter, Object obj, XmlObjectSerializerWriteContextComplexJson context, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.Json.XmlObjectSerializerWriteContextComplexJson.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph)
at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph)
at System.Runtime.Serialization.XmlObjectSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.Json.DataContractJsonSerializer.WriteObject(XmlDictionaryWriter writer, Object graph)
at System.Runtime.Serialization.Json.DataContractJsonSerializer.WriteObject(Stream stream, Object graph)
at TestJson.Program.Main(String[] args) in c:\src\TestJson\Program.cs:line 44
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()
InnerException:
完整的代码是:
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
namespace TestJson
{
class Program
{
static void Main(string[] args)
{
Adult parent = new Adult {name = "John", age = 42};
MemoryStream stream1 = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Adult));
ser.WriteObject(stream1, parent);
stream1.Position = 0;
StreamReader sr = new StreamReader(stream1);
Console.Write("JSON form of Adult with no children: ");
Console.WriteLine(sr.ReadToEnd());
Child child = new Child { name = "Jane", age = 4, fingers=10 };
stream1 = new MemoryStream();
ser = new DataContractJsonSerializer(typeof(Child));
ser.WriteObject(stream1, child);
stream1.Position = 0;
sr = new StreamReader(stream1);
Console.Write("JSON form of Child with no parent: ");
Console.WriteLine(sr.ReadToEnd());
// now connect the two
parent.children.Add(child);
stream1 = new MemoryStream();
ser = new DataContractJsonSerializer(typeof(Adult));
ser.WriteObject(stream1, parent);
stream1.Position = 0;
sr = new StreamReader(stream1);
Console.Write("JSON form of Adult with 1 child: ");
Console.WriteLine(sr.ReadToEnd());
}
}
[DataContract]
class Person
{
[DataMember]
internal string name;
[DataMember]
internal int age;
}
[DataContract]
class Adult : Person
{
[DataMember]
internal List<Person> children = new List<Person>();
}
[DataContract]
class Child : Person
{
[DataMember]
internal int fingers;
}
}
答案 0 :(得分:1)
只需按照异常消息中提供的建议操作,并将KnownType
属性添加到Person
:
[DataContract]
[KnownType(typeof(Parent))]
[KnownType(typeof(Child))]
class Person
{
[DataMember]
internal string name;
[DataMember]
internal int age;
}
您需要通过基类的KnownType
属性主动使序列化引擎知道派生类型。
at 与递归对象无关。