从 class 中获取 JSON 属性 名称的列表以在查询字符串中使用
Get a list of JSON property names from a class to use in a query string
如果我有一个 C# 模型 class 被 JSON.net 用于绑定来自序列化 JSON 字符串的数据,有没有一种方法可以从中创建查询字符串class 是为了提出最初的要求?
型号class示例:
public class model
{
[JsonProperty(PropertyName = "id")]
public long ID { get; set; }
[JsonProperty(PropertyName = "some_string")]
public string SomeString {get; set;}
}
查询字符串示例:
baseUrl + uri + "&fields=id,some_string" + token
所以我要做的本质是从模型对象中收集 "id" 和 "some_string",这样我就可以动态创建“&fields”参数。谢谢!
您可以使用反射来做到这一点。这是总体思路:
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Reflection;
namespace ConsoleApplication8
{
public class model
{
[JsonProperty(PropertyName = "id")]
public long ID { get; set; }
[JsonProperty(PropertyName = "some_string")]
public string SomeString { get; set; }
}
internal class Program
{
private static void Main(string[] args)
{
var model = new model();
var result = string.Empty;
PropertyInfo[] props = typeof(model).GetProperties();
foreach (PropertyInfo prop in props)
{
foreach (object attr in prop.GetCustomAttributes(true))
{
result += (attr as JsonPropertyAttribute).PropertyName;
}
}
}
}
}
@Leigh Shepperson 的想法是正确的;但是,您可以使用 LINQ 以更少的代码完成此操作。我会创建一个这样的辅助方法:
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
...
public static string GetFields(Type modelType)
{
return string.Join(",",
modelType.GetProperties()
.Select(p => p.GetCustomAttribute<JsonPropertyAttribute>())
.Select(jp => jp.PropertyName));
}
你可以这样使用它:
var fields = "&fields=" + GetFields(typeof(model));
编辑
如果您 运行 使用的是 .Net Framework 3.5 版本,因此您没有可用的通用 GetCustomAttribute<T>
方法,您可以使用非泛型 GetCustomAttributes()
方法,将其与 SelectMany
和 Cast<T>
:
一起使用
return string.Join(",",
modelType.GetProperties()
.SelectMany(p => p.GetCustomAttributes(typeof(JsonPropertyAttribute))
.Cast<JsonPropertyAttribute>())
.Select(jp => jp.PropertyName)
.ToArray());
在模型仅部分用 [JsonProperty(PropertyName = "XXX")]
属性注释,或用 data contract attributes, or has ignored properties, you can use Json.NET's own contract resolver 注释以获取序列化 属性 名称列表的情况下。首先介绍一下扩展方法:
public static class JsonExtensions
{
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();
}
}
然后,执行:
// Allocate the relevant contract resolver.
// Options are CamelCasePropertyNamesContractResolver() or DefaultContractResolver().
IContractResolver resolver = new DefaultContractResolver();
// Get properties
var propertyNames = resolver.PropertyNames(typeof(model));
var fields = "&fields=" + String.Join(",", propertyNames);
对于 resolver
使用 CamelCasePropertyNamesContractResolver
if you are camel casing your property names (which ASP.NET Core Web API does ); otherwise use DefaultContractResolver
。
示例 fiddle.
解决空异常问题的@Brian Rogers 解决方案的一个小变体:
IEnumerable<string> props = typeof(T).GetProperties()
.Select(p => p.GetCustomAttribute<JsonPropertyAttribute>())
.Where(jp => jp != null)
.Select(jp => jp.PropertyName);
string propsList = string.Join(',', props);
public class CreateContactProperties
{
[JsonProperty("email")] public string email { get; set; }
[JsonProperty("firstname")] public string firstname { get; set; }
}
public string GetJsonPropertyFieldName(PropertyInfo t)
{
var attr = t.GetCustomAttributes(typeof(JsonPropertyAttribute), true).FirstOrDefault() as JsonPropertyAttribute;
return attr.PropertyName;
}
IList<PropertyInfo> entityprops = new List<PropertyInfo>(typeof(CreateContactProperties).GetProperties());
foreach (var item in entityprops)
{
properties += $"{GetJsonPropertyFieldName(item)}, ";
}
如果我有一个 C# 模型 class 被 JSON.net 用于绑定来自序列化 JSON 字符串的数据,有没有一种方法可以从中创建查询字符串class 是为了提出最初的要求?
型号class示例:
public class model
{
[JsonProperty(PropertyName = "id")]
public long ID { get; set; }
[JsonProperty(PropertyName = "some_string")]
public string SomeString {get; set;}
}
查询字符串示例:
baseUrl + uri + "&fields=id,some_string" + token
所以我要做的本质是从模型对象中收集 "id" 和 "some_string",这样我就可以动态创建“&fields”参数。谢谢!
您可以使用反射来做到这一点。这是总体思路:
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Reflection;
namespace ConsoleApplication8
{
public class model
{
[JsonProperty(PropertyName = "id")]
public long ID { get; set; }
[JsonProperty(PropertyName = "some_string")]
public string SomeString { get; set; }
}
internal class Program
{
private static void Main(string[] args)
{
var model = new model();
var result = string.Empty;
PropertyInfo[] props = typeof(model).GetProperties();
foreach (PropertyInfo prop in props)
{
foreach (object attr in prop.GetCustomAttributes(true))
{
result += (attr as JsonPropertyAttribute).PropertyName;
}
}
}
}
}
@Leigh Shepperson 的想法是正确的;但是,您可以使用 LINQ 以更少的代码完成此操作。我会创建一个这样的辅助方法:
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
...
public static string GetFields(Type modelType)
{
return string.Join(",",
modelType.GetProperties()
.Select(p => p.GetCustomAttribute<JsonPropertyAttribute>())
.Select(jp => jp.PropertyName));
}
你可以这样使用它:
var fields = "&fields=" + GetFields(typeof(model));
编辑
如果您 运行 使用的是 .Net Framework 3.5 版本,因此您没有可用的通用 GetCustomAttribute<T>
方法,您可以使用非泛型 GetCustomAttributes()
方法,将其与 SelectMany
和 Cast<T>
:
return string.Join(",",
modelType.GetProperties()
.SelectMany(p => p.GetCustomAttributes(typeof(JsonPropertyAttribute))
.Cast<JsonPropertyAttribute>())
.Select(jp => jp.PropertyName)
.ToArray());
在模型仅部分用 [JsonProperty(PropertyName = "XXX")]
属性注释,或用 data contract attributes, or has ignored properties, you can use Json.NET's own contract resolver 注释以获取序列化 属性 名称列表的情况下。首先介绍一下扩展方法:
public static class JsonExtensions
{
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();
}
}
然后,执行:
// Allocate the relevant contract resolver.
// Options are CamelCasePropertyNamesContractResolver() or DefaultContractResolver().
IContractResolver resolver = new DefaultContractResolver();
// Get properties
var propertyNames = resolver.PropertyNames(typeof(model));
var fields = "&fields=" + String.Join(",", propertyNames);
对于 resolver
使用 CamelCasePropertyNamesContractResolver
if you are camel casing your property names (which ASP.NET Core Web API does DefaultContractResolver
。
示例 fiddle.
解决空异常问题的@Brian Rogers 解决方案的一个小变体:
IEnumerable<string> props = typeof(T).GetProperties()
.Select(p => p.GetCustomAttribute<JsonPropertyAttribute>())
.Where(jp => jp != null)
.Select(jp => jp.PropertyName);
string propsList = string.Join(',', props);
public class CreateContactProperties
{
[JsonProperty("email")] public string email { get; set; }
[JsonProperty("firstname")] public string firstname { get; set; }
}
public string GetJsonPropertyFieldName(PropertyInfo t)
{
var attr = t.GetCustomAttributes(typeof(JsonPropertyAttribute), true).FirstOrDefault() as JsonPropertyAttribute;
return attr.PropertyName;
}
IList<PropertyInfo> entityprops = new List<PropertyInfo>(typeof(CreateContactProperties).GetProperties());
foreach (var item in entityprops)
{
properties += $"{GetJsonPropertyFieldName(item)}, ";
}