使用IXmlSerializable对象的WCF JSON序列化

时间:2013-02-15 09:06:46

标签: json wcf serialization

我有结构IntEx - 简而言之它扩展了正常的Int32和处理过的操作。它看起来像这样:

[Serializable]
public struct IntEx
{
    private int internalValue;

    private IntEx(int value)
    {
        internalValue = value;
    }

    public static implicit operator int(IntEx value)
    {
        return value.internalValue;
    }

    public static implicit operator IntEx(int value)
    {
        return new IntEx(value);
    }
}

如果我们通过WCF发送这个结构,它使用JSON进行序列化,输出将“很好看”。就像我们将使用下面的示例代码:

DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(TestClass));

using (MemoryStream stream = new MemoryStream())
{
    jsonSerializer.WriteObject(stream, testClass);

    string serializedString = Encoding.UTF8.GetString(stream.GetBuffer());

    Console.WriteLine("JSON: {0}", serializedString);
}
public class TestClass
{
    public int I1 { get; set; }

    public IntEx I2 { get; set; }
}

输出看起来像这样

JSON: {"I1":11,"I2":{"internalValue":22}}

客户端和其他“第三方”程序使用此格式(使用 internalValue )。

使用IntEx在我的应用程序中广泛使用。其中一个对象被序列化为XML(某种设置)。此对象使用IntEx作为类型。 所以我必须实现IXmlSerializable来构造IntEx,因为没有这个属性被序列化为空节点

XML: <TestClass><I1>11</I1><I2 /></TestClass>

如果我更改IntEx以使用IXmlSerializable

[Serializable]
public struct IntEx : IXmlSerializable
{
    private int internalValue;

    private IntEx(int value)
    {
        internalValue = value;
    }

    public static implicit operator int(IntEx value)
    {
        return value.internalValue;
    }

    public static implicit operator IntEx(int value)
    {
        return new IntEx(value);
    }

    System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
    {
        return null;
    }

    void IXmlSerializable.ReadXml(System.Xml.XmlReader reader)
    {
        throw new NotImplementedException();
    }

    void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteValue(internalValue);
    }
}

XML输出看起来不错

XML: <TestClass><I1>11</I1><I2>22</I2></TestClass>

但是我的所有服务都崩溃了,因为现在JSON看起来像这样:

JSON: {"I1":11,"I2":"<IntEx xmlns=\"http:\/\/schemas.datacontract.org\/2004\/07\/TestJSONSerialization\">22<\/IntEx>"}

我读到如果你使用IXmlSerializable,JSON序列化“认为”我负责序列化,所以把这个对象留给我......但是我怎样才能改回“原始”序列化。

所以现在我处于deadend ...我需要JSON输出看起来像以前一样,但我还需要一些强制写入设置为XML的两个条件:

  1. internalValue应该保持私有 - 使用某些公共属性
  2. 不应该访问它
  3. 我不想将一堆代码重写为chaneg(使用装箱来获取JSON的属性)或更改所有可以保存到XML文件的属性或类。
  4. 那么有人能给我一些线索,我该如何解决这个问题? :/

1 个答案:

答案 0 :(得分:0)

您可以将DataContractJsonSerializer与IDataContractSurrogate一起使用。使用IDataContractSurrogate将“IntEx”转换为“IntExJson”,而“IntExJson”不需要从IXmlSerializable继承。

IDataContractSurrogate可用于从对象中删除某些功能,并转换为类似的对象。然后使用:

public DataContractJsonSerializer(Type type, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, IDataContractSurrogate dataContractSurrogate, bool alwaysEmitTypeInformation);

将对象序列化为json。反序列化是一样的。