3

Based on certain conditions I need to deserialize JSON strings into different models, sometimes model A, sometimes model B. However in the model A there are JsonPropertyName attributes from System.Text.Json.Serialization while in class B there are JsonProperty attributes from Newtonsoft.Json. The issue is that the JSON strings correspond to the actual property names and not to the names given in the attributes. I would like to make the JSON serializer, either Newtonsoft or System.Text to ignore its own attributes. It that possible?

That's an example JSON string:

{
  "PropertyOne" : "some value"
}

And here is an example model:

public class A
{
  [JsonProperty("property_one")]
  public string PropertyOne{ get; set; }
}
public class B
{
  [JsonPropertyName("property_one")]
  public string PropertyOne{ get; set; }
}

PS I can't change the models

LilacBlue
  • 173
  • 1
  • 9
  • I'm assuming Newtonsoft.Json will ignore System.Text.Json attributes and vice-versa, so you might need to work with Newtonsoft when deserializing one class and with System.Text.Json when deserializing the other. – Zohar Peled Jan 24 '23 at 13:50
  • 2
    Sounds like a job for a custom contract resolver. You can see a somewhat related example here: https://stackoverflow.com/a/20639697/625594 – Sergey Kudriavtsev Jan 24 '23 at 13:53

1 Answers1

3

As Sergey Kudriavtsev suggested in the comments section, the custom contract resolver worked well for my use case. I will leave the solution for anyone who has a similar problem.

Here is the custome contract resolver class:

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;

namespace mynamespace
{
  public class DefaultNameContractResolver : DefaultContractResolver
  {
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
      // Let the base class create all the JsonProperties 
      IList<JsonProperty> list = base.CreateProperties(type, memberSerialization);

      // Now inspect each property and replace the name with the real property name
      foreach (JsonProperty prop in list)
      {
        prop.PropertyName = prop.UnderlyingName;
      }
      return list;
    }
  }
}

Here is how to use it:

string json = "{ \"PropertyOne\" : \"some value\" }";
Type recordType = typeof(A);
Newtonsoft.Json.JsonSerializerSettings settings = new()
{
  ContractResolver = new mynamespace.DefaultNameContractResolver()
};
var myObject = Newtonsoft.Json.JsonConvert.DeserializeObject(json, recordType, settings);
LilacBlue
  • 173
  • 1
  • 9