What is the equivalent of Newtonsoft.Json's / Json.Net's JsonProperty field in System.Text.Json?

Viewed 6076

I wanted to know what the euqivalent of the Newtonsoft.Json's / Json.Net's JsonProperty field in System.Text.Json is.

Example:

using Newtonsoft.Json;

public class Example
{
    [JsonProperty("test2")]
    public string Test { get; set; }
}

References:

2 Answers

Note for anyone who finds this looking to replace Newtonsoft with System.Text.Json specifically getting a private property to serialize. Newtonsoft will happily serialize a private property with the Newtonsoft.Json.JsonProperty attribute, but putting System.Text.Json.Serialization.JsonPropertyName on a private property doesn't work. For example:

enum Animal { Cat, Dog }
class Foo
{
    [Newtonsoft.Json.JsonProperty("animals")]
    [System.Text.Json.Serialization.JsonPropertyName("animals")]
    private string AnimalForSerializer
    {
        get => AnimalForMe.ToString() + "s";
        set => AnimalForMe = Enum.Parse<Animal>(value.TrimEnd('s'));
    }
 
    [System.Text.Json.Serialization.JsonIgnore]
    [Newtonsoft.Json.JsonIgnore]
    public Animal AnimalForMe { get; set; }
}

var b = new Foo { AnimalForMe = Animal.Dog };

var json = System.Text.Json.JsonSerializer.Serialize(b);
var fromJson = System.Text.Json.JsonSerializer.Deserialize<Foo>(json);
Console.WriteLine($"{json} -> {fromJson.AnimalForMe}");

json = Newtonsoft.Json.JsonConvert.SerializeObject(b);
fromJson = Newtonsoft.Json.JsonConvert.DeserializeObject<Foo>(json);
Console.WriteLine($"{json} -> {fromJson.AnimalForMe}");

Outputs

{} -> Cat
{"animals":"Dogs"} -> Dog

To replace this behavior you need JsonInclude. Or rather, to almost replace. The System.Text.Json team decided not to support private properties. If you try you will get an error like "The non-public property 'AnimalForSerializer' on type 'Foo' is annotated with 'JsonIncludeAttribute' which is invalid.". But you can have a private setter, apparently:


class Foo
{
    [Newtonsoft.Json.JsonProperty("animals")]
    [System.Text.Json.Serialization.JsonInclude]
    [System.Text.Json.Serialization.JsonPropertyName("animals")]
    public string AnimalForSerializer
    {
        get => AnimalForMe.ToString() + "s";
        private set => AnimalForMe = Enum.Parse<Animal>(value.TrimEnd('s'));
    }
    
    [System.Text.Json.Serialization.JsonIgnore]
    [Newtonsoft.Json.JsonIgnore]
    public Animal AnimalForMe { get; set; }
}

var b = new Foo { AnimalForMe = Animal.Dog };

var json = System.Text.Json.JsonSerializer.Serialize(b);
var fromJson = System.Text.Json.JsonSerializer.Deserialize<Foo>(json);
Console.WriteLine($"{json} -> {fromJson.AnimalForMe}");

json = Newtonsoft.Json.JsonConvert.SerializeObject(b);
fromJson = Newtonsoft.Json.JsonConvert.DeserializeObject<Foo>(json);
Console.WriteLine($"{json} -> {fromJson.AnimalForMe}");

Outputs

{"animals":"Dogs"} -> Dog
{"animals":"Dogs"} -> Dog

Of course, not having private breaks encapsulation, but what can you do.

Related