具有对象类型成员的DataContractJsonSerializer [英] DataContractJsonSerializer with object type member

查看:88
本文介绍了具有对象类型成员的DataContractJsonSerializer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下序列化方法:

private string Serialize(Message message)
{
    byte[] json;

    using (var ms = new MemoryStream())
    {
        var ser = new DataContractJsonSerializer(typeof(Message));
        ser.WriteObject(ms, message);
        json = ms.ToArray();
    }

    return Encoding.UTF8.GetString(json, 0, json.Length);
}

我正在尝试序列化以下对象:

I'm trying to serialize the following object:

[DataContract]
public class Message
{
    [DataMember(Name = "technical", Order = 1)]
    public Technical Technical;

    [DataMember(Name = "payload", Order = 2)]
    public object Payload;
}

[DataContract]
public class Technical
{
    [DataMember(Name = "topic", Order = 1)]
    public string Topic { get; set; }

    [DataMember(Name = "nature", Order = 2)]
    public string Nature { get; set; }

    [DataMember(Name = "event_id", Order = 3)]
    public string EventId { get; set; }
}

我面临与 object 参数,该参数包含具有 DataContract DataMember的 AuthorizationRequest 对象。这是完整的异常堆栈跟踪:

I'm facing a serialization exception related to the object parameter containing an AuthorizationRequest object having DataContract and DataMember too. Here is the complete exception stack trace :


L'exception System.Runtime.Serialization.SerializationException n'a
更多信息参数代码utilisateur HResult = -2146233076

消息= Le类型
'AF.WS.ProjetEtDevis.DAP.MNG.BusinessEntities.AuthorizationRequest'
从名义上使用
'AuthorizationRequest: http:// schemas。 datacontract.org/2004/07/AF.WS.ProjetEtDevis.DAP.MNG.BusinessEntities '
n'est pas出席者。 Utilisez联合国DataContractResolver SI VOUS utilisez
DataContractSerializer的OU ajoutez TOUS LES类型的非connus
statiquement点菜清单当然DES类型connus,票面为例EN utilisant
L'attribut KnownTypeAttribute欧卫浴莱ajoutant点菜清单当然DES类型
连续发送请求。

Source = System.Runtime.Serialization StackTrace:
àSystem.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract
dataContract, XmlWriterDelegator xmlWriter,对象obj,布尔值
verifyKnownType,RuntimeTypeHandle声明的类型句柄,类型
的声明类型)
àSystem.Runtime.Serialization.Json.XmlObjectSerializerWriteContextComplexJson.SerializeWithXsiType(XmlWriterDeObject RuntimeTypeHandle objectTypeHandle,类型
objectType,Int32声明的类型ID,RuntimeTypeHandle
声明的类型手形,类型的声明的类型)
àSystem.Runtime.Serializati on.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator
xmlWriter,Object obj,布尔值isDeclaredType,布尔型writeXsiType,
Int32声明的类型ID,RuntimeTypeHandle的声明的类型句柄)
àSystem.Runtime.Sialerizer。 $ b xmlWriter,Object obj,布尔值isDeclaredType,布尔值writeXsiType,
Int32声明的TypeID,RuntimeTypeHandle的声明的类型Handle)
àWriteMessageToJson(XmlWriterDelegator,Object,XmlObjectSerializerWriteContextComplexJson,ClassDataContract,
XmlD) àSystem.Runtime.Serialization.Json.JsonClassDataContract.WriteJsonValueCore(XmlWriterDelegator
jsonWriter,Object obj,XmlObjectSerializerWriteContextComplexJson
上下文,RuntimeTypeHandle声明的TypeHandle)
àSystem.Runtime.Seriason。数据公司ntract
dataContract,XmlWriterDelegator xmlWriter,Object obj,
RuntimeTypeHandleclarifiedTypeHandle)
àSystem.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract
dataContract,XmlWriterDeleger $ b RuntimeTypeHandleclarifiedTypeHandle)
àSystem.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObjectContent(XmlWriterDelegator
writer,Object graph)
àSystem.Runtime.Serialization.Json.DataContractXsonSerializer(InnerWriteObject()
writer,对象图)
àSystem.Runtime.Serialization.XmlObjectSerializer.InternalWriteObject(XmlWriterDelegator
writer,对象图,DataContractResolver dataContractResolver)
àSystem.Runtime.Serialization.XmlObjectSerializer。 WriteObjectHandleExceptions(XmlWriterDelegator
writer,Object graph,DataContractResolver dataContractResolver)
àSystem.Runtime.Serialization.Json.DataContractJsonSerializer.WriteObject(XmlDictionaryWriter
writer,对象图)
àSystem.Runtime.Serialization.Json.DataContractJsonSerializer.WriteObject(流
流,对象图)
àAF.WS.ProjetEtDevis.DAP.MNG.BusinessLogic.AuthorizationRequestMngService.Serialize(Message
message)dans
C:\src\Git\AF.WS.ProjetEtDevis.DAP .MNG\来源\AF.WS.ProjetEtDevis.DAP.MNG.BusinessLogic\AuthorizationRequestMngService.cs:ligne
134
àAF.WS.ProjetEtDevis.DAP.MNG.BusinessLogic.AuthorizationRequestMngService.GenerateEdaMessage (字符串
topicName,AuthorizationRequest请求)dans
C:\src\Git\AF.WS.ProjetEtDevis.DAP.MNG\源\AF.WS.ProjetEtDevis.DAP.MNG。 BusinessLogic\AuthorizationRequestMngService.cs:ligne
124
àAF.WS.ProjetEtDevis.DAP.MNG.UnitTests._2._BusinessLogic_Tests.AuthorizationRequestMngServiceUnitTest.ShouldSerializeAuthoriza tionRequest_WhenCorrectDataSent()
dans
C:\src\Git\AF.WS.ProjetEtDevis.DAP.MNG\源\AF.WS.ProjetEtDevis.DAP.MNG.UnitTests\2 。
BusinessLogic测试\AuthorizationRequestMngServiceUnitTest.cs:ligne
251 InnerException:

L'exception System.Runtime.Serialization.SerializationException n'a pas été gérée par le code utilisateur HResult=-2146233076
Message=Le type 'AF.WS.ProjetEtDevis.DAP.MNG.BusinessEntities.AuthorizationRequest' avec le nom de contrat de données 'AuthorizationRequest:http://schemas.datacontract.org/2004/07/AF.WS.ProjetEtDevis.DAP.MNG.BusinessEntities' n'est pas attendu. Utilisez un DataContractResolver si vous utilisez DataContractSerializer ou ajoutez tous les types non connus statiquement à la liste des types connus, par exemple en utilisant l'attribut KnownTypeAttribute ou en les ajoutant à la liste des types connus qui est transmise au sérialiseur.
Source=System.Runtime.Serialization StackTrace: à System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType) à System.Runtime.Serialization.Json.XmlObjectSerializerWriteContextComplexJson.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType) à System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle) à System.Runtime.Serialization.XmlObjectSerializerWriteContextComplex.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle) à WriteMessageToJson(XmlWriterDelegator , Object , XmlObjectSerializerWriteContextComplexJson , ClassDataContract , XmlDictionaryString[] ) à System.Runtime.Serialization.Json.JsonClassDataContract.WriteJsonValueCore(XmlWriterDelegator jsonWriter, Object obj, XmlObjectSerializerWriteContextComplexJson context, RuntimeTypeHandle declaredTypeHandle) à System.Runtime.Serialization.Json.XmlObjectSerializerWriteContextComplexJson.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) à System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) à System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph) à System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph) à System.Runtime.Serialization.XmlObjectSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) à System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) à System.Runtime.Serialization.Json.DataContractJsonSerializer.WriteObject(XmlDictionaryWriter writer, Object graph) à System.Runtime.Serialization.Json.DataContractJsonSerializer.WriteObject(Stream stream, Object graph) à AF.WS.ProjetEtDevis.DAP.MNG.BusinessLogic.AuthorizationRequestMngService.Serialize(Message message) dans C:\src\Git\AF.WS.ProjetEtDevis.DAP.MNG\Sources\AF.WS.ProjetEtDevis.DAP.MNG.BusinessLogic\AuthorizationRequestMngService.cs:ligne 134 à AF.WS.ProjetEtDevis.DAP.MNG.BusinessLogic.AuthorizationRequestMngService.GenerateEdaMessage(String topicName, AuthorizationRequest request) dans C:\src\Git\AF.WS.ProjetEtDevis.DAP.MNG\Sources\AF.WS.ProjetEtDevis.DAP.MNG.BusinessLogic\AuthorizationRequestMngService.cs:ligne 124 à AF.WS.ProjetEtDevis.DAP.MNG.UnitTests._2._BusinessLogic_Tests.AuthorizationRequestMngServiceUnitTest.ShouldSerializeAuthorizationRequest_WhenCorrectDataSent() dans C:\src\Git\AF.WS.ProjetEtDevis.DAP.MNG\Sources\AF.WS.ProjetEtDevis.DAP.MNG.UnitTests\2. BusinessLogic Tests\AuthorizationRequestMngServiceUnitTest.cs:ligne 251 InnerException:

英语中的消息是:


类型'AF.WS.ProjetEtDevis.DAP.MNG.BusinessEntities.AuthorizationRequest',数据合同名称为'AuthorizationRequest: http://schemas.datacontract.org/2004/07/AF.WS。不应使用ProjetEtDevis.DAP.MNG.BusinessEntities 。将静态未知的任何类型添加到已知类型的列表中,例如,通过使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知类型的列表中。

Type 'AF.WS.ProjetEtDevis.DAP.MNG.BusinessEntities.AuthorizationRequest' with data contract name 'AuthorizationRequest:http://schemas.datacontract.org/2004/07/AF.WS.ProjetEtDevis.DAP.MNG.BusinessEntities' is not expected. 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.

请注意,除了 DataContractJsonSerializer

推荐答案

您需要预先通知 DataContractJsonSerializer 对象有效载荷成员,方法是使用已知类型机制。来自 docs

You need to inform DataContractJsonSerializer upfront of the possible types that might occur in the object Payload member by using the known type mechanism. From the docs:


多态

多态序列化包含在预期其基本类型的地方对派生类型进行序列化的能力。与支持XML序列化的方式相比,WCF对JSON序列化提供了支持。例如,您可以在需要MyBaseType的地方序列化MyDerivedType,或者在可以期望Object的地方序列化Int ...

Polymorphic serialization consists of the ability to serialize a derived type where its base type is expected. This is supported for JSON serialization by WCF comparable to the way XML serialization is supported. For example, you can serialize MyDerivedType where MyBaseType is expected, or serialize Int where Object is expected...

保存类型信息

如前所述,JSON支持多态,但有一些限制...

As stated earlier, polymorphism is supported in JSON with some limitations...

在序列化复杂对象时保留类型标识将类型添加到JSON时,可以添加类型提示,并且反序列化器会识别该提示并采取适当的措施。 类型提示是密钥名称为 __type的JSON键/值对(两个下划线,后跟单词 type)。该值是形式为 DataContractName:DataContractNamespace的JSON字符串(名称中最多第一个冒号)。

To preserve type identity, when serializing complex types to JSON a "type hint" can be added, and the deserializer recognizes the hint and acts appropriately. The "type hint" is a JSON key/value pair with the key name of "__type" (two underscores followed by the word "type"). The value is a JSON string of the form "DataContractName:DataContractNamespace" (anything up to the first colon is the name).

最常见的方法是应用 KnownTypeAttribute 到相关数据协定对象本身:

The most common way to do this is to apply KnownTypeAttribute to the relevant data contract object itself:

[DataContract]
[KnownType(typeof(AuthorizationRequest))]
public class Message
{
    [DataMember(Name = "technical", Order = 1)]
    public Technical Technical;

    [DataMember(Name = "payload", Order = 2)]
    public object Payload;
}

您也可以使用 DataContractJsonSerializer(Type,IEnumerable< Type>) 构造函数:

You can also use the DataContractJsonSerializer(Type, IEnumerable<Type>) constructor:

var ser = new DataContractJsonSerializer(typeof(Message), new [] { typeof(AuthorizationRequest)});

这样做,您的序列化JSON将如下所示,且多态类型提示<$ c $包括c> __ type 来指定有效负载类型:

Having done so, your serialized JSON will look as follows, with the polymorphic type hint __type included to specify the payload type:

{
  "technical": {
    "topic": "my topic",
    "nature": "my nature",
    "event_id": "1010101"
  },
  "payload": {
    "__type": "AuthorizationRequest:#Question48583688"
  }
}

如果在指定已知类型方面需要更大的灵活性,请参见动态配置已知类型-介绍DataContractResolver 。但是请确保不允许解析所有类型。如果这样做,您将向您的应用程序引入安全性问题,例如在Newtonsoft Json中 TypeNameHandling警告中讨论的那些问题。

If you need more flexibility in how known types are specified, see Configuring Known Types Dynamically – Introducing the DataContractResolver. But be sure not to allow any and all types to be resolved. If you do, you will introduce security problems into your app like those discussed in TypeNameHandling caution in Newtonsoft Json.

这篇关于具有对象类型成员的DataContractJsonSerializer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆