1

I need to Deserialize object having 2 fields as string and one dictionary, i tried to convert but it throwing error as "Cannot serialize member MVVMDemo.Model.Student.books of type System.Collections.Generic.Dictionary" it is doable when there is no dictionary item in but when i add that dictionary item it fail to convert. throwing error from below line

XmlSerializer serializer = new XmlSerializer(typeof(Student));

Here is my class

public class Student
    {
        private string firstName;
        private string lastName;
        public Dictionary<string, string> books;

        public Dictionary<string, string> Books
        {
            get{return books;}
            set{books = value;}
        }
        public string FirstName
        {
            get{return firstName;}
            set
            {
                if (firstName != value)
                {
                    firstName = value;
                }
            }
        }

        public string LastName
        {
            get { return lastName; }
            set
            {
                if (lastName != value)
                {
                    lastName = value;
                }
            }
        }
    }
madan
  • 773
  • 13
  • 38
  • 1
    Would this help? https://stackoverflow.com/questions/12554186/how-to-serialize-deserialize-to-dictionaryint-string-from-custom-xml-not-us – Renat Jul 15 '19 at 10:48
  • in both example a separate dictionary used, for that i can create a class and deserialize it but my object having 2 string item and one dictionary item. – madan Jul 15 '19 at 10:58
  • this nuget package can serialize class that has dictionary as a member: https://github.com/wojtpl2/ExtendedXmlSerializer/blob/master/docs/get-started/index.rst ; normal XmlSerializer serializer data annotations also work with this library; it also has the ability to serialize references [in serializer configuration: .ConfigureType().EnableReferences(o => o.ID)], to objects instead of whole objects – Arie Jul 15 '19 at 13:51

2 Answers2

1

You can solve this with Newtonsoft.Json library. To serialize start with converting your object to json, then use DeserializeXNode method:

var student = new Student()
{
    FirstName = "FirstName",
    LastName = "LastName",
    Books = new Dictionary<string, string>
    {
        { "abc", "42" },
    }
};

var json = JsonConvert.SerializeObject(student);
var xml = JsonConvert.DeserializeXNode(json, "Root");
var result = xml.ToString(SaveOptions.None);
// result is "<Root><books><abc>42</abc></books><Books><abc>42</abc></Books><FirstName>FirstName</FirstName><LastName>LastName</LastName></Root>"

To deserialize you can use SerializeXmlNode method:

var input = "<Root><books><abc>42</abc></books><Books><abc>42</abc></Books><FirstName>FirstName</FirstName><LastName>LastName</LastName></Root>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(input);
var json = JsonConvert.SerializeXmlNode(doc);
var template = new {Root = (Student) null};
var result = JsonConvert.DeserializeAnonymousType(json, template);
// result.Root is an instance of Student class
Aleks Andreev
  • 7,016
  • 8
  • 29
  • 37
1

The reason why Dictionary is not supported by the XmlSerializer is that types such as Dictionary, HashTable, etc. needs an equality comparer which can’t be serialized into XML easily. To get around this problem

Use DataContractSerizalizer

[DataContract]
public class Student
{
    private string firstName;
    private string lastName;

    private Dictionary<string, string> books = new Dictionary<string, string>();
    [DataMember]
    public Dictionary<string, string> Books
    {
        get => books;
        set => books = value;
    }
    [DataMember]
    public string FirstName
    {
        get { return firstName; }
        set
        {
            if (firstName != value)
            {
                firstName = value;
            }
        }
    }
    [DataMember]
    public string LastName
    {
        get { return lastName; }
        set
        {
            if (lastName != value)
            {
                lastName = value;
            }
        }
    }
}


var serializer = new DataContractSerializer(typeof(Student));
            using (var sw = new StringWriter()){
                using (var writer = new XmlTextWriter(sw))
                {
                    serializer.WriteObject(writer, student);
                    writer.Flush();
                    var xml = sw.ToString();
                }
            }
Artem Vertiy
  • 1,002
  • 15
  • 31