.net - 如何将递归类型转换为 JSON

  显示原文与译文双语对照的内容
0 0

如何转换具有递归类型( 不是对象,只是类型)的对象? 当尝试序列化具有父/子关系的对象时,以下代码失败。

错误是对 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:srcTestJsonProgram.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;
 }
}
时间:原作者:4个回答

0 0

简单地按照异常消息给出的建议操作,并将 KnownType 属性添加到 Person:

[DataContract]
[KnownType(typeof(Parent))]
[KnownType(typeof(Child))]
class Person
{
 [DataMember]
 internal string name;
 [DataMember]
 internal int age;
}

你需要通过基类上的KnownType 属性,主动地使序列化引擎知道派生类型。
你的问题与递归无关,在递归对象上。

原作者:
...