C# 从类中获取要在查询字符串中使用的JSON属性名称列表

C# 从类中获取要在查询字符串中使用的JSON属性名称列表,c#,json,json.net,.net-3.5,query-string,C#,Json,Json.net,.net 3.5,Query String,如果我有一个C#model类,JSON.net使用该类绑定序列化JSON字符串中的数据,那么有没有一种方法可以从该类创建查询字符串以发出初始请求 模型类示例: public class model { [JsonProperty(PropertyName = "id")] public long ID { get; set; } [JsonProperty(PropertyName = "some_string")] public string SomeString {g

如果我有一个C#model类,JSON.net使用该类绑定序列化JSON字符串中的数据,那么有没有一种方法可以从该类创建查询字符串以发出初始请求

模型类示例:

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
查询字符串示例:

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;
                }
            }
        }
    }
}

@利·谢泼森的想法是正确的;但是,使用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
方法可用,则可以使用非通用的
GetCustomAttributes()
方法,将其与
SelectMany
Cast
一起使用:

返回string.Join(“,”,
modelType.GetProperties()
.SelectMany(p=>p.GetCustomAttributes(typeof(JsonPropertyAttribute))
.Cast())
.Select(jp=>jp.PropertyName)
.ToArray());

如果模型仅使用
[JsonProperty(PropertyName=“XXX”)]
属性进行部分注释,或者使用属性进行注释,或者具有属性,则可以使用Json.NET自己的属性来获取序列化属性名的列表。首先,介绍以下扩展方法:

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
如果要使用驼峰式大小写,请使用属性名称(ASP.NET Core Web API就是这样做的);否则使用


示例。

解决空异常问题的@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);
IEnumerable props=typeof(T).GetProperties()
.Select(p=>p.GetCustomAttribute())
.Where(jp=>jp!=null)
.Select(jp=>jp.PropertyName);
string-propsList=string.Join(“,”,props);

谢谢Brian,这是一个真正优雅的解决方案。我应该在问题中做得更好,我会在这次会议后更新。我使用的是Unity3D,即修改后的.net 3.5,似乎4.5中的getcustomattributes被赋予了泛型类型。您的问题最初被标记为
Unity3D
,但由于问题似乎与此无关,我将其删除并在其位置添加了
Json.net
。我已经更新了我的答案,向您展示了如何在.NET 3.5.Perfect中使用非泛型的
GetCustomAttributes()
方法来做同样的事情,谢谢。只是在最后一个select语句后添加了一个.toArray()。@RoLYroLLs-您的编辑不正确;它跳过了没有
[JsonProperty(PropertyName=“XXX”)]
属性的属性,而不是返回c#属性名称。你真的应该问另一个关于这种情况的问题,但是我补充了在这种情况下该怎么做。谢谢你,我将尝试在我的问题中使用这个