Josh Close
Josh Close

Reputation: 23383

DataContractSerializer returning null for all values when using CollectionDataContract

I have some data referenced here http://docs.microsofttranslator.com/text-translate.html#!/default/post_TranslateArray

<ArrayOfTranslateArrayResponse 
    xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2" 
    xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <TranslateArrayResponse>
        <From>en</From>
        <OriginalTextSentenceLengths 
            xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
            <a:int>14</a:int>
        </OriginalTextSentenceLengths>
        <TranslatedText>Esto es una prueba</TranslatedText>
        <TranslatedTextSentenceLengths 
            xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
            <a:int>18</a:int>
        </TranslatedTextSentenceLengths>
    </TranslateArrayResponse>
    <TranslateArrayResponse>
        <From>en</From>
        <OriginalTextSentenceLengths 
            xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
            <a:int>22</a:int>
        </OriginalTextSentenceLengths>
        <TranslatedText>Hola, yo tengo una manzana</TranslatedText>
        <TranslatedTextSentenceLengths 
            xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
            <a:int>26</a:int>
        </TranslatedTextSentenceLengths>
    </TranslateArrayResponse>
</ArrayOfTranslateArrayResponse>

I'm trying to deserialize this data using a DataContractSerializer. All the values in the collection are null. I can serialize using this same structure and it comes out the same as this text, but it won't deserialize. Here is the code.

void Main()
{
    var xmlString = "<ArrayOfTranslateArrayResponse xmlns=\"http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><TranslateArrayResponse><From>language-code</From><OriginalTextSentenceLengths xmlns:a=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\"><a:int>int-value</a:int></OriginalTextSentenceLengths><State/><TranslatedText>string-value</TranslatedText><TranslatedTextSentenceLengths xmlns:a=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\"><a:int>int-value</a:int></TranslatedTextSentenceLengths></TranslateArrayResponse></ArrayOfTranslateArrayResponse>";
    var dcs = new DataContractSerializer(typeof(TranslateArrayResponseCollection));

    using (var stream = new MemoryStream())
    using (var writer = new StreamWriter(stream))
    {
        writer.Write(xmlString);
        writer.Flush();
        stream.Position = 0;

        dcs.ReadObject(stream).Dump();
    }
}

[CollectionDataContract(Name = "ArrayOfTranslateArrayResponse", Namespace = "http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2")]
public class TranslateArrayResponseCollection : List<TranslateArrayResponse> { }

[DataContract(Name = "TranslateArrayResponse", Namespace = "")]
public class TranslateArrayResponse
{
    [DataMember]
    public string Error { get; set; }

    [DataMember]
    public string From { get; set; }

    [DataMember]
    public int[] OriginalSentenceLengths { get; set; }

    [DataMember]
    public string TranslatedText { get; set; }

    [DataMember]
    public int[] TranslatedSentenceLengths { get; set; }

    [DataMember]
    public string State { get; set; }
}

Upvotes: 1

Views: 1880

Answers (1)

CodeFuller
CodeFuller

Reputation: 31282

In your XML data arrays are named OriginalTextSentenceLengths and TranslatedTextSentenceLengths. But in your data contract they are OriginalSentenceLengths and TranslatedSentenceLengths. You should rename them in data contract:

[DataMember]
public string TranslatedText { get; set; }

[DataMember]
public int[] TranslatedTextSentenceLengths { get; set; }

Another problem is missing namespace for the elements. After I have added empty namespace xmlns="" to all elements the data is deserialized correctly. Here is modified XML:

<ArrayOfTranslateArrayResponse 
    xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2" 
    xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <TranslateArrayResponse>
        <From xmlns="">en</From>
        <OriginalTextSentenceLengths xmlns=""
            xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
            <a:int>14</a:int>
        </OriginalTextSentenceLengths>
        <TranslatedText xmlns="">Esto es una prueba</TranslatedText>
        <TranslatedTextSentenceLengths xmlns=""
            xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
            <a:int>18</a:int>
        </TranslatedTextSentenceLengths>
    </TranslateArrayResponse>
    <TranslateArrayResponse>
        <From xmlns="">en</From>
        <OriginalTextSentenceLengths xmlns=""
            xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
            <a:int>22</a:int>
        </OriginalTextSentenceLengths>
        <TranslatedText xmlns="">Hola, yo tengo una manzana</TranslatedText>
        <TranslatedTextSentenceLengths xmlns=""
            xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
            <a:int>26</a:int>
        </TranslatedTextSentenceLengths>
    </TranslateArrayResponse>
</ArrayOfTranslateArrayResponse>

I believe it's the limitation of DataContractSerializer. Check this question with exactly the same problem. You should either modify source XML by adding the namespace or use XmlSerializer which should handle this case.

Upvotes: 2

Related Questions