4

I have a class as mentioned below:

public class Employee {

    [JsonProperty("emp_id")]
    public int Id {get; set;}

    [JsonProperty("emp_fname")]
    public string Name {get;set;}

    [JsonProperty("emp_lname")]
    public string LastName {get;set;} 
}

In the above class, I have assigned Newtonsoft Attribute for serialization.

I have a object of class Employee and Now I would like to find the property by JsonProperty and get value of that property.

For example, I would like to get the value of the property for which JsonProprty attribute name is set to emp_lname

Is there a way to find value like this using reflection?

2
  • I believe the JsonProperty tags are used for deserialization of a string. Within your code, if you have the Json deserialized, you would use Name instead of emp_fname to access the value. Commented Jan 18, 2020 at 18:58
  • 1
    var pInfo = [EmployeeInstance].GetType().GetProperties().FirstOrDefault(p => p.GetCustomAttributes<JsonPropertyAttribute>().Any(at => at.PropertyName.Equals("emp_lname"))); Commented Jan 18, 2020 at 19:08

1 Answer 1

7

You can use Json.NET's own contract resolver for this purpose. Doing so will correctly handle properties with, and without, [JsonProperty(string name)] attributes added, as well as objects with naming strategies or data contract attributes applied directly.

First add the following method:

public static partial class JsonExtensions
{
    static readonly IContractResolver defaultResolver = JsonSerializer.CreateDefault().ContractResolver;

    public static object GetJsonProperty<T>(T obj, string jsonName, bool exact = false, IContractResolver resolver = null)
    {
        if (obj == null)
            throw new ArgumentNullException(nameof(obj));
        resolver = resolver ?? defaultResolver;
        var contract = resolver.ResolveContract(obj.GetType()) as JsonObjectContract;
        if (contract == null)
            throw new ArgumentException(string.Format("{0} is not serialized as a JSON object", obj));
        var property = contract.Properties.GetProperty(jsonName, exact ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
        if (property == null)
            throw new ArgumentException(string.Format("Property {0} was not found.", jsonName));
        return property.ValueProvider.GetValue(obj); // Maybe check JsonProperty.Readable first, and throw an exception if not?
    }
}

And now you can do:

var employee = new Employee
{
    LastName = "last name",
};

Console.WriteLine("Value of {0} is {1}.", "emp_lname", 
                  JsonExtensions.GetJsonProperty(employee, "emp_lname")); // Prints Value of emp_lname is last name.

If your app uses camel casing for JSON serialization by default, you can pass a CamelCasePropertyNamesContractResolver in for resolver like so:

Console.WriteLine("Value of {0} is {1}.", "emp_lname", 
                  JsonExtensions.GetJsonProperty(employee, "emp_lname", resolver : new CamelCasePropertyNamesContractResolver())); 

If you need to get a list of all JSON property names for a given type, see Get a list of JSON property names from a class to use in a query string:

public static partial class JsonExtensions
{
    public static string [] PropertyNames(Type type)
    {
        return PropertyNames(defaultResolver, type);
    }

    //Taken from this answer https://stackoverflow.com/a/45829514/3744182
    //To https://stackoverflow.com/questions/33616005/get-a-list-of-json-property-names-from-a-class-to-use-in-a-query-string
    public static string [] PropertyNames(this IContractResolver resolver, Type type)
    {
        if (resolver == null || type == null)
            throw new ArgumentNullException();
        var contract = resolver.ResolveContract(type) as JsonObjectContract;
        if (contract == null)
            return new string[0];
        return contract.Properties.Where(p => !p.Ignored).Select(p => p.PropertyName).ToArray();
    }
}

Demo fiddle here.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.