У меня есть следующий класс.
public class Foo
{
[XmlElement("Bar", typeof(Bar))]
[XmlElement("Pub", typeof(Pub))]
public BaseBar Bar { get; set; }
}
Я хотел бы перейти от сериализации XML к сериализации JSON (System.Text.Json
), что эквивалентно атрибуту [XmlElement("Bar", typeof(Bar))]
?
Смотрите этот образец: https://dotnetfiddle.net/pU8QAU
Редактировать:
Я ищу способ определить его на уровне свойств, поэтому, если у меня есть 2 свойства, я хотел бы иметь для них разные имена.
public class Foo
{
[XmlElement("Bar", typeof(Bar))]
[XmlElement("Pub", typeof(Pub))]
public BaseBar Bar { get; set; }
[XmlElement("Bar2", typeof(Bar))]
[XmlElement("Pub2", typeof(Pub))]
public BaseBar Bar2 { get; set; }
}
Смотрите этот образец: https://dotnetfiddle.net/M6nla
Редактировать2:
Данный ответ Гуру Строна дает этот результат
{"Bar":{"$type":"Pub" …
я ищу
{"Pub":{…
Где Pub
должно быть сериализовано из свойства Bar
, если оно имеет тип Pub
.
🤔 А знаете ли вы, что...
C# также используется для разработки игр с помощью Unity3D, популярного игрового движка.
.NET 7 и последняя версия System.Text.Json
представили поддержку полиморфной сериализации json. Один из способов справиться с этим — использовать JsonDerivedTypeAttribute
для базового типа, указав всех потомков:
[JsonDerivedType(typeof(Bar), typeDiscriminator: nameof(Bar))]
[JsonDerivedType(typeof(Pub), typeDiscriminator: nameof(Pub))]
public abstract class BaseBar
{
public abstract string Text { get; set; }
}
public class Bar : BaseBar
{
public override string Text { get; set; } = "I am a Bar";
}
public class Pub : BaseBar
{
public override string Text { get; set; } = "I am a Pub";
}
Пользовательский преобразователь предыдущей версии .NET 7 можно было использовать для поддержки полиморфной десериализации.
Чтобы сериализовать ваши данные, вам даже не нужен атрибут имени элемента, если у вас такое же имя свойства и вам не нужен корневой класс, вы можете использовать словарь
var foo = new Dictionary<string, BaseBar> {
{ "Bar", new Bar() },
{ "Pub", new Pub() }
};
var json = System.Text.Json.JsonSerializer.Serialize(foo,
new JsonSerializerOptions{WriteIndented = true}
);
выход
{
"Bar": {
"Text": "I am a Bar"
},
"Pub": {
"Text": "I am a Pub"
}
}
десериализовать
Dictionary<string, BaseBar> foo = JsonObject.Parse(json).AsObject()
.ToDictionary(p => p.Key, p => p.Key == "Bar" ?
(BaseBar)p.Value.Deserialize<Bar>()
: (BaseBar)p.Value.Deserialize<Pub>()
);