Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserializing a List of KeyValuePairs

I have some XML in the following format:

<ObjectData>
  <ModelName>MODEL_123</ModelName>
  <ObjectName>OBJECT_A</ObjectName>
  <Values>
    <KeyValuePair>
      <Key>NAME</Key>
      <Value>PAUL</Value>
    </KeyValuePair>
    ...
  </Values>
</ObjectData>
...

I want to deserialize this into the following class:

[XmlRoot(Namespace = "")]
public class ObjectData
{
    [XmlElement(Namespace = "")]
    public string ModelName { get; set; }
    [XmlElement(Namespace = "")]
    public string ObjectName { get; set; }
    [XmlArray]
    public List<KeyValuePair<string, string>> Values { get; set; }
}

When I use this code, the KeyValuePairs are not deserialized and the Values property is empty.

List<ObjectData> data = new List<ObjectData>();
XmlSerializer serializer = new XmlSerializer(typeof(ObjectData));

using (XmlReader reader = XmlReader.Create(new StringReader(inputXML)))
{             
    reader.MoveToContent();
    ObjectData temp = (ObjectData)serializer.Deserialize(reader);
    data.Add(temp);
}  

Is the KeyValuePair class not serializable in the way I use it? Or is there a problem in my ObjectData class?

like image 645
Paul Avatar asked Feb 06 '12 19:02

Paul


3 Answers

Try specifying the element names in your attributes:

[XmlArray("Values")]
[XmlArrayItem("KeyValuePair")]
public List<KeyValuePair<string, string>> Values { get; set; }
like image 169
D Stanley Avatar answered Nov 15 '22 09:11

D Stanley


Combining D Stanley's answer with this post, I was able to come up with the right structure:

[XmlRoot(Namespace = "")]
public class ObjectData
{
    [XmlElement(Namespace = "")]
    public string ModelName { get; set; }
    [XmlElement(Namespace = "")]
    public string ObjectName { get; set; }
    [XmlArray("Values")]
    [XmlArrayItem("KeyValuePair")] 
    public List<KeyValuePair<string, string>> Values { get; set; }
}

[Serializable]
public class KeyValuePair<K, V> {
    public K Key { get; set; }
    public V Value { get; set; }
    public KeyValuePair() { }
    public KeyValuePair(K key, V value)
    {
        this.Key = key;
        this.Value = value;
    }
}
like image 27
Paul Avatar answered Nov 15 '22 08:11

Paul


There is no setter for Key or Value in the KeyValuePair struct. You'll have to change the data type. You can decorate the property so you can name the new type whatever you want.

....
    [XmlArray("Values")]
    [XmlArrayItem("KeyValuePair")]  //not needed if MyItem is named KeyValuePair
    public List<MyItem> Values { get; set; }
}

public class MyItem
{
    public string Key { get; set; }
    public string Value { get; set; }
}
like image 43
Austin Salonen Avatar answered Nov 15 '22 09:11

Austin Salonen