如果具有嵌套属性返回类型的属性返回类型接口,则DataContractJsonSerializer问题

时间:2018-08-09 13:39:14

标签: c# json c#-4.0

需要序列化为JSON字符串并将JSON字符串反序列化为对象。

这是我的课程流程。

[DataContract]
public class BatchItem_NF : INF
{
    [DataMember]
    public IDebtor Debtor { get; set; }

    [DataMember]
    public IList<IDebtor> AllDebtors
    {
        get
        {
            return _debtors;
        }
    }
}

[DataContract]
public class Debtor : IDebtor
{
    [DataMember]
    public IAddress Address { get; set; }
    [DataMember]
    public string Name { get; set; }
}
[DataContract]
public class Address : IAddress
{
    [DataMember]
    public string Street { get; set; }
    [DataMember]
    public string City { get; set; }
}

这是我要序列化但无法正常工作的内容

private string BatchItem_NFSerialization(INF Alldebtors)
{
    Type t = Alldebtors.GetType();
    extraTypes1 = t.GetProperties()
        .Where(p => p.PropertyType.IsInterface)
        .Select(p => p.GetValue(Alldebtors, null).GetType())
        .ToArray();
    using (MemoryStream ms = new MemoryStream())
    {
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(t, extraTypes1);
        serializer.WriteObject(ms, ((BatchItem_NF)Alldebtors));

        retVal = Encoding.Default.GetString(ms.ToArray());
    }
}

它抛出以下错误: 不应使用数据合同名称为“地址:http://schemas.datacontract.org/2004/07/”的类型“地址”。如果您正在使用DataContractSerializer或将任何静态未知的类型添加到已知类型的列表中,请考虑使用DataContractResolver-例如,通过使用KnownTypeAttribute属性或将它们添加到传递给序列化程序的已知类型的列表中

有人可以帮助

1 个答案:

答案 0 :(得分:0)

您仅对第一级属性获得已知类型。在您的代码中,您仅获得Debtor类型,但还应处理此属性以例如通过递归获得Address类型。

private static string BatchItem_NFSerialization(INF Alldebtors)
{
    Type t = Alldebtors.GetType();
    var extraTypes1 = GetKnownTypes(Alldebtors);

    using (MemoryStream ms = new MemoryStream())
    {
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(t, extraTypes1);
        serializer.WriteObject(ms, ((BatchItem_NF)Alldebtors));

        var retVal = Encoding.Default.GetString(ms.ToArray());
        return retVal;
    }
}

private static IEnumerable<Type> GetKnownTypes(object property)
{
    Type t = property.GetType();

    var extraValues = t.GetProperties()
        .Where(p => p.PropertyType.IsInterface && !p.PropertyType.IsGenericType)
        .Select(p => p.GetValue(property, null))
        .ToArray();

    var extraTypes = extraValues.SelectMany(GetKnownTypes).ToArray();

    return extraValues.Select(v => v.GetType()).Concat(extraTypes).ToArray();
}