I'm using System.Web.Script.Serialization.JavaScriptSerializer
to serialize / deserialize a class that extends Dictionary.
The problem is, my custom properties are not being serialized. Here is my class:
public class Test : Dictionary<string, object> {
public ushort Id { get; set; }
public string Name { get; set; }
}
And my code:
var jss = new JavaScriptSerializer();
var test = new Test {
Id = 123,
Name = "test"
};
var json = jss.Serialize(test);
The result in json
is an empty json {}
I do not want to depend on Newtonsoft or JSON.Net or any other library.
ADDITIONAL INFO
I just noticed some, hm, peculiarities, when using both dynamic
and object
:
JavaScriptSerializer
defaults any number value toint
.Also,
Newtonsoft
defaults any number tolong
.
That can cause casting exceptions in a class using property indexer (as suggested in the accepted answer), for example:
public class Test : Dictionary<string, dynamic> {
public ushort Id { get => this[nameof(Id)]; set => this[nameof(Id)] = value; }
}
The Id
property getter will try to implicitly convert int
to ushort
, which will fail.
ADDITIONAL INFO 2
I just found out so many weird behaviors with Newtonsoft:
I added these attributes to solve the 'long to ushort' problem:
[JsonObject(MemberSerialization.OptIn)]
public class Test : Dictionary<string, dynamic> {
[JsonProperty]
public ushort Id { get => this[nameof(Id)]; set => this[nameof(Id)] = value; }
}
The above works! But when the property is a reference type:
[JsonObject(MemberSerialization.OptIn)]
public class Test : Dictionary<string, dynamic> {
[JsonProperty]
public ushort Id { get => this[nameof(Id)]; set => this[nameof(Id)] = value; }
[JsonProperty]
public Test Child { get => this[nameof(Child)]; set => this[nameof(Child)] = value; }
}
It tries to get the property before serializing it, resulting in a 'key not found exception'. I can't see why it tries to get the property only when it's a reference type, seems like a bug to me...
So you have to do something like this:
public Test Child { get => this.ContainsKey(index) ? this[nameof(Child)] : null; ... }