如何在 C# 中使用反射获取 Json 属性名称

con*_*per 4 c# json.net system.reflection

我有一堂课,如下所述:

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;} 
}
Run Code Online (Sandbox Code Playgroud)

在上面的类中,我为序列化分配了 Newtonsoft 属性。

我有一个类对象Employee,现在我想找到该属性JsonProperty并获取该属性的值。

例如,我想获取 JsonProprty 属性名称设置为的属性的值emp_lname

有没有办法使用反射来找到这样的价值?

dbc*_*dbc 6

您可以使用 Json.NET 自己的合约解析器来实现此目的。这样做可以正确处理添加或不[JsonProperty(string name)]添加属性的属性,以及直接应用命名策略数据协定属性的对象。

首先添加以下方法:

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?
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以这样做:

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.
Run Code Online (Sandbox Code Playgroud)

如果您的应用程序默认使用驼峰式大小写进行 JSON 序列化,则可以像这样传入CamelCasePropertyNamesContractResolverfor :resolver

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

如果您需要获取给定类型的所有 JSON 属性名称的列表,请参阅从类获取要在查询字符串中使用的 JSON 属性名称列表

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

    //Taken from this answer /sf/answers/3208066011/
    //To /sf/ask/2353120381/
    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();
    }
}
Run Code Online (Sandbox Code Playgroud)

演示小提琴在这里