1

I have the following class.

public class Foo { [XmlElement("Bar", typeof(Bar))] [XmlElement("Pub", typeof(Pub))] public BaseBar Bar { get; set; } } 

I would like to move from XML serialization to JSON (System.Text.Json) serialization, what is the equivalent for the attribute [XmlElement("Bar", typeof(Bar))]?

See this sample: https://dotnetfiddle.net/pU8QAU

Edit:

I am looking for a way to define it on property level, so if I have 2 properties I would like to have different names for those.

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; } } 

See this sample: https://dotnetfiddle.net/M6nla

Edit2:

The given answer by Guru Stron produces this output

{"Bar":{"$type":"Pub" … 

I am looking for

{"Pub":{… 

Where Pub should be serialized from the property Bar if it is of type Pub.

2
  • I don't think f there is similar attribute but you can go for custom serializer or you can have both properties and third one which would be a base type and return first non null value of them (and setter yould set one of them based on type) Commented Feb 13, 2023 at 21:46
  • 1
    ...like this... Commented Feb 14, 2023 at 12:32

2 Answers 2

4

.NET 7 and latest version of System.Text.Json have introduced support for polymorphic json serialization. One way to handle it is to use JsonDerivedTypeAttribute on the base type specifying all descendants:

[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"; } 

Prior .NET 7 custom converter could be used to support polymorphic deserialization.

Sign up to request clarification or add additional context in comments.

5 Comments

You could get polymorphic deserialization to work pre-.NET 7, but it wasn't for the faint of heart
So I can’t specify it on property level eg. if I had two properties with the same class and both with different names?
As an example you can see this: dotnetfiddle.net/M6nlaV
Had another look at the json output of your example, and have another question. I would have preferred if the propertyName it self would have changed to reflect the type so instead of {"Bar":{"$type":"Pub" … I would prefer {"Pub":{…
@RandRandom that is not how standard json serialization works, but you can write your own serializer. Which will work until you have two properties of the same base type with the same actual value type (it is recommended to have your keys in json to be unique).
1

To serialize you data, you even don't need any element name attribute, if you have the same property name and you don't need a root class, you can use a Dictionary

 var foo = new Dictionary<string, BaseBar> { { "Bar", new Bar() }, { "Pub", new Pub() } }; var json = System.Text.Json.JsonSerializer.Serialize(foo, new JsonSerializerOptions{WriteIndented = true} ); 

output

{ "Bar": { "Text": "I am a Bar" }, "Pub": { "Text": "I am a Pub" } } 

to deserialize

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>() ); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.