48

What is the equivalent of Newtonsoft.Json's JsonProperty attribute in System.Text.Json?

Example:

using Newtonsoft.Json;

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

References:

Miles Buckton
  • 23
  • 1
  • 6
FranzHuber23
  • 3,311
  • 5
  • 24
  • 63

2 Answers2

70

Just in case, anyone else falls over this. The property is renamed to JsonPropertyName and comes from System.Text.Json.Serialization in the System.Text.Json nuget package.

Example:

using System.Text.Json.Serialization;

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

References:

FranzHuber23
  • 3,311
  • 5
  • 24
  • 63
7

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.

Aaron B
  • 859
  • 11
  • 17