Search code examples
c#json.netjson.netsystem.text.json

Is there a way to have Json.NET honor the System.Text.Json JsonPropertyName attribute


I have a C# type that represents a deserialized C# payload. But it's deserialized in one place by System.Text.Json. In another place, it's Json.NET.

So right now, I have to attribute the properties using both [JsonProperty] (for Json.NET) and [JsonPropertyName] (for System.Text.Json).

Is there a way to tell Json.NET recognize the JsonPropertyName attribute so I don't have to annotate each property twice?


Solution

  • You can create custom contract resolver which will search for JsonPropertyName attribute and use value from it. Example one can look something like that:

    public class ContractResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty property = base.CreateProperty(member, memberSerialization);
    
            if (member.GetCustomAttribute<JsonPropertyNameAttribute>() is {} stj)
            {
                property.PropertyName = stj.Name;
                return property;
            }
    
            return property;
        }
    }
    

    And usage:

    class MyClass
    {
        [JsonProperty("P1")]
        public int MyProperty { get; set; }
        [JsonPropertyName("P2")]
        public int MyProperty2 { get; set; }
    }
    
    var settings = new JsonSerializerSettings
    {
        ContractResolver = new ContractResolver()
    };  
    
    Console.WriteLine(JsonConvert.SerializeObject(new MyClass(), settings)); // prints {"P1":0,"P2":0}
    Console.WriteLine(JsonConvert.DeserializeObject<MyClass>("{'P1':1,'P2':2}", settings).MyProperty2); // prints 2