微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

IExtensibleDataObject 是否与 EmitDefaultValue 选项和 DataContractJsonSerializer 一起使用?

如何解决IExtensibleDataObject 是否与 EmitDefaultValue 选项和 DataContractJsonSerializer 一起使用?

我想设计一个 API,它接受一些通用契约,并且还可以存储扩展通用架构的附加值。看起来 IExtensibleDataObject 机器是为类似任务而构建的,它对我的​​用例很有用。

但是,当我尝试使用它时,我发现在 ExtensionDataObject 使用 EmitDefaultValue = false 选项时 DataMember 属性反序列化的奇怪行为。

考虑以下数据契约(注意Item DTO 的字段具有 EmitDefaultValue = false 选项):

[DataContract(Name = "Contract",Namespace = "")]
public class ContractGeneric : IExtensibleDataObject
{
    [DataMember(Name = "id",Order = 1)]
    public string Id;

    public ExtensionDataObject? ExtensionData { get; set; }
}

[DataContract(Name = "Contract",Namespace = "")]
public class ContractExtended
{
    [DataMember(Name = "id",Order = 1)]
    public string Id;

    [DataMember(Name = "items",Order = 2)]
    public Item[] Items;
}

[DataContract(Name = "Item",Namespace = "")]
public class Item
{
    [DataMember(Name = "code",Order = 1,EmitDefaultValue = false)]
    public string Code;

    [DataMember(Name = "name",Order = 2,EmitDefaultValue = false)]
    public string Name;
}

契约的定义对我来说看起来不错,但是从带有 ContractGenericContractExtended DTO 解析的 DataContractJsonSerializer DTO 的序列化可能会因奇怪的异常而崩溃:

Unhandled exception. System.Runtime.Serialization.SerializationException: There was an error serializing the object of type TestSerialization.ContractGeneric. Encountered unexpected el
ement local name 'code' for item in collection. 'item' is the only valid local name for elements in a collection.

例如,您可以通过以下示例获得崩溃情况:

public class Program
{
    public static void Main()
    {
        var v2 = new ContractExtended {Id = "1",Items = new[] {new Item {Code = "0"}}};
        var v2Json = ToJson(v2);
        Console.WriteLine(v2Json);
        var v1 = FromJson<ContractGeneric>(v2Json);
        var v1Json = ToJson(v1);
        Console.WriteLine(v1Json);
    }
    
    public static string ToJson<T>(T value)
    {
        using var memoryStream = new MemoryStream();
        new DataContractJsonSerializer(typeof(T)).WriteObject(memoryStream,value);
        return Encoding.UTF8.GetString(memoryStream.ToArray());
    }

    public static T FromJson<T>(string json)
    {
        using var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json));
        return (T) new DataContractJsonSerializer(typeof(T)).Readobject(memoryStream);
    }
}

看起来反序列化过程中存在错误,内部Extendedobject认为items集合的一个元素也是一个集合,但这是错误的,序列化器仅在当时检测到这种差异序列化过程。

我能否在保留 EmitDefaultValue 选项的同时避免这种奇怪的异常,并保持在 JSON 世界中(因为 XML 序列化似乎可以正确处理这种情况)。或者这是 DataContractJsonSerializer错误或某种限制?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。