Serializing WCF JSON on an Object with IXmlSerializable

I have an IntEx structure - in short it extends a normal Int32 and is processed. It looks like this:

[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);
    }
}

      

If we send this structure through WCF, it is serialized using JSON and the output looks pretty. How we will use the example code below:

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; }
}

      

The result looks like this

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

      

The client and other third-party programs use this format (with internalValue ).

Using IntEx is widely used in my application. One of the objects is serialized to XML (some customization). This object uses IntEx as its type. So I have to implement IXmlSerializable for IntEx structure, because without this property is serialized as empty node

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

      

If I change IntEx to use 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 output looks ok

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

      

but all my services are breaking as now the JSON looks like this:

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

      

I read that if you are using IXmlSerializable, JSON serialization "think" I am in charge of serialization, leave this object to me ... But how can I go back to the "original" serialization.

So now I find myself in a dead situation. I need JSON output as before, but I also need how to get the settings to be written for XML with two conditions:

  • internalValue must remain private - it must not be accessible using some public property
  • I don't want to rewrite a bunch of chaneg code (use boxing for JSON properties) or change every possible property or class that can be stored in an XML file.

So can someone tell me how I can solve this problem?: /

+3


source to share


1 answer


you can use DataContractJsonSerializer with IDataContractSurrogate. using IDataContractSurrogate to convert "IntEx" to "IntExJson" and "IntExJson" doesn't need to inherit from IXmlSerializable.

IDataContractSurrogate can be used to remove some objects from an object and convert to a similar object. and then use:



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

      

to serialize the object to json. deserialization is the same.

0


source







All Articles