How to get a JSON property name matching the naming strategy for a model?

Viewed 208

Say an application has serializer settings with CamelCasePropertyNamesContractResolver and I have a model:

public class Model
{
    public int Id { get; set; }

    [JsonProperty(Name = "content_text")]
    public string Text { get; set; }
}

I'd like to find a way to get the resulting name a serializer would generate on serialize for each property, so that following would be true:

string JsonName<T>(string cSharpPropertyName)
{
    //
}

JsonName<Model>(nameof(Model.Id)) == "id";
JsonName<Model>(nameof(Model.Text)) == "content_text";

I'm writing a custom deserializer (JSON converter) for a custom type and I'd like to match my Model properties with JSON input without being case insensitive but with the current serializer strategy.

I had idea to just deserialize each incoming JToken wrapped in a new JSON object to a c# object and check resulting property name but it doesn't seem to be very efficient. Is there a better way to do this?

1 Answers

You can use the contract resolver itself to do this job.

Make your JsonName method accept an IContractResolver as a parameter along with the property name. The implementation might look something like this:

public static string JsonName<T>(string cSharpPropertyName, IContractResolver resolver) where T : class
{
    var contract = resolver.ResolveContract(typeof(T)) as JsonObjectContract;
    var property = contract?.Properties.FirstOrDefault(p => p.UnderlyingName == cSharpPropertyName);
    return property?.PropertyName;
}

Inside your JsonConverter, you can get the contract resolver from the serializer, which is provided as a parameter to ReadJson:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    var resolver = serializer.ContractResolver;
    ...
}
Related