如何在 C# 中使用反射获取 Json 属性 名称
How to get Json Property name using reflection in C#
我有一个 class 如下所述:
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;}
}
在上面的class中,我为序列化分配了Newtonsoft属性。
我有一个 class Employee
的对象,现在我想通过 JsonProperty
找到 属性 并获取 属性 的值。
例如,我想获取 JsonProprty 属性名称设置为 emp_lname
的 属性 的值
有没有办法使用反射找到这样的值?
可以使用Json.NET自己的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直接应用
首先添加如下方法:
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?
}
}
现在您可以:
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.
如果您的应用默认使用驼峰式大小写 JSON 序列化,您可以像这样为 resolver
传递一个 CamelCasePropertyNamesContractResolver
:
Console.WriteLine("Value of {0} is {1}.", "emp_lname",
JsonExtensions.GetJsonProperty(employee, "emp_lname", resolver : new CamelCasePropertyNamesContractResolver()));
如果您需要获取给定类型的所有 JSON 属性 名称的列表,请参阅 :
public static partial class JsonExtensions
{
public static string [] PropertyNames(Type type)
{
return PropertyNames(defaultResolver, type);
}
//Taken from this answer
//To
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();
}
}
演示 fiddle here.
我有一个 class 如下所述:
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;}
}
在上面的class中,我为序列化分配了Newtonsoft属性。
我有一个 class Employee
的对象,现在我想通过 JsonProperty
找到 属性 并获取 属性 的值。
例如,我想获取 JsonProprty 属性名称设置为 emp_lname
有没有办法使用反射找到这样的值?
可以使用Json.NET自己的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直接应用
首先添加如下方法:
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?
}
}
现在您可以:
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.
如果您的应用默认使用驼峰式大小写 JSON 序列化,您可以像这样为 resolver
传递一个 CamelCasePropertyNamesContractResolver
:
Console.WriteLine("Value of {0} is {1}.", "emp_lname",
JsonExtensions.GetJsonProperty(employee, "emp_lname", resolver : new CamelCasePropertyNamesContractResolver()));
如果您需要获取给定类型的所有 JSON 属性 名称的列表,请参阅
public static partial class JsonExtensions
{
public static string [] PropertyNames(Type type)
{
return PropertyNames(defaultResolver, type);
}
//Taken from this answer
//To
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();
}
}
演示 fiddle here.