red9350
red9350

Reputation: 378

C# KeyValuePair deserialization of a list as "value" field

I have a KeyValuePair object serialized in XML, and for every key, there is a list of values like so:

<WritableKeyValuePairOfKeyContraenteArrayOfAddress>
   <key>
      <KeyContaente>123456</KeyContaente>
   </key>
   <value>
      <Address>Maple road 12</Address>
   </value>
   <value>
      <Address>Oak street 71</Address>
   </value>
</WritableKeyValuePairOfKeyContraenteArrayOfAddress>

The problem is: when I deserialize, the object's value contains just one element: the first ("Maple road 12"). Why does this happen?

EDIT: Serialization:

public static string Serializza<T>(T objectToSerialize)
    {
        using (MemoryStream memStm = new MemoryStream())
        {
            var serializer = new DataContractSerializer(typeof(T));
            serializer.WriteObject(memStm, objectToSerialize);

            memStm.Seek(0, SeekOrigin.Begin);

            using (var streamReader = new StreamReader(memStm))
            {
                string result = streamReader.ReadToEnd();
                return result;
            }
        }
    }

Deserialization:

    private static T Deserializza<T>(string xmlString)
    {
        if (xmlString.Length > 0)
        {
            try
            {
                var serializer = new DataContractSerializer(typeof(T));
                using (System.IO.MemoryStream memStm = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(xmlString)))
                {
                    return (T)serializer.ReadObject(memStm);
                }
            }
            catch
            {
                return default(T);
            }
        }
        else
            return default(T);
    }

KeyValuePair is like a Dictionary:

[Serializable, StructLayout(LayoutKind.Sequential)]
public class WritableKeyValuePair<TKey, TValue> : IWritableKeyValuePair
{
    private TKey key;
    private TValue value;

    public WritableKeyValuePair() { }
    public WritableKeyValuePair(TKey key, TValue value)
    {
        this.key = key;
        this.value = value;
    }

    public override string ToString()
    {
        return WKVPUtils<TKey, TValue>.ToString(key, value);
    }

    ////[XmlProcessDeep()]
    public TValue Value
    {
        get { return this.value; }
        set { this.value = value; }
    }

    public TKey Key
    {
        get { return this.key; }
        set { this.key = value; }
    }

    internal static class WKVPUtils<TKey, TValue>
    {
        public static string ToString(TKey Key, TValue Value)
        {
            StringBuilder builder1 = new StringBuilder();
            builder1.Append('[');
            if (Key != null)
                builder1.Append(Key.ToString());
            builder1.Append(", ");
            if (Value != null)
                builder1.Append(Value.ToString());
            builder1.Append(']');
            return builder1.ToString();
        }
    }
}

Upvotes: 1

Views: 407

Answers (2)

halfer
halfer

Reputation: 20487

(Posted on behalf of the OP).

This is solved. I had to edit the XML structure as follows:

<WritableKeyValuePairOfKeyContraenteArrayOfAddress>
   <key>
      <KeyContaente>123456</KeyContaente>
   </key>
   <value>
      <Address>Maple road 12</Address>
      <Address>Oak street 71</Address>
   </value>
</WritableKeyValuePairOfKeyContraenteArrayOfAddress>

Before I had a <value> tag for each <Address> tag, now there's just one opening and closing <value> tag, containing multiple <Address> tags.

Upvotes: 1

jdweng
jdweng

Reputation: 34433

try this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml =
                "<Root>" +
                "<WritableKeyValuePairOfKeyContraenteArrayOfAddress>" +
                   "<key>" +
                      "<KeyContaente>123456</KeyContaente>" +
                   "</key>" +
                   "<value>" +
                      "<Address>Maple road 12</Address>" +
                      "<Address>Oak street 71</Address>" +
                   "</value>" +
                "</WritableKeyValuePairOfKeyContraenteArrayOfAddress>" +
                "</Root>";

            XElement elements = XElement.Parse(xml);

            Dictionary<string, List<string>> dict = elements.Descendants("WritableKeyValuePairOfKeyContraenteArrayOfAddress").Select(x => new
            {
                key = (string)x.Descendants("KeyContaente").FirstOrDefault(),
                values = x.Descendants("Address").Select(y => (string)y).ToList()
            }).GroupBy(x => x.key, y => y.values)
            .ToDictionary(x => x.Key, y => y.FirstOrDefault());
        }
    }
}

Upvotes: 0

Related Questions