skip to Main Content

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

Answers


  1. .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.

    Login or Signup to reply.
  2. 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>()
                                        );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search