Я использую System.Web.Script.Serialization.JavaScriptSerializer
для сериализации / десериализации класса, расширяющего словарь.
Проблема в том, что мои пользовательские свойства не сериализуются.Вот мой класс:
public class Test : Dictionary<string, object> {
public ushort Id { get; set; }
public string Name { get; set; }
}
И мой код:
var jss = new JavaScriptSerializer();
var test = new Test {
Id = 123,
Name = "test"
};
var json = jss.Serialize(test);
Результат в json
это пустой JSON {}
Я не хочузависеть от Newtonsoft или JSON.Net или любой другой библиотеки.
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ
Я только что заметил некоторые, хм, особенности при использовании как dynamic
, так и object
:
JavaScriptSerializer
по умолчанию любое числовое значение равно int
.
Кроме того, Newtonsoft
по умолчанию любое число long
.
Это может привести к исключениям приведения в классе с использованием индексатора свойств (как предлагается в принятом ответе), например:
public class Test : Dictionary<string, dynamic> {
public ushort Id { get => this[nameof(Id)]; set => this[nameof(Id)] = value; }
}
Id
getter попытается неявно преобразовать int
в ushort
, что приведет к сбою.
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ 2
Я только что обнаружил так много странного поведения с Newtonsoft:
Я добавил эти атрибуты для решения проблемы 'long to ushort':
[JsonObject(MemberSerialization.OptIn)]
public class Test : Dictionary<string, dynamic> {
[JsonProperty]
public ushort Id { get => this[nameof(Id)]; set => this[nameof(Id)] = value; }
}
Вышеприведенное работает!Но когда свойство является ссылочным типом:
[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; }
}
Оно пытается получить свойство перед его сериализацией, что приводит к «исключению ключа не найден».Я не понимаю, почему он пытается получить свойство только тогда, когда он является ссылочным типом, для меня это похоже на ошибку ...
Так что вы должны сделать что-то вроде этого:
public Test Child { get => this.ContainsKey(index) ? this[nameof(Child)] : null; ... }