Get a list of JSON property names from a class to use in a query string

后端 未结 4 1337
清歌不尽
清歌不尽 2020-12-10 11:48

If I have a C# model class that is used by JSON.net to bind data from a serialized JSON string, is there a way that I can create a query string from that class in order to m

相关标签:
4条回答
  • 2020-12-10 12:31

    A small variation of @Brian Rogers solution that solve null exception problem:

    IEnumerable<string> props = typeof(T).GetProperties()
                                         .Select(p => p.GetCustomAttribute<JsonPropertyAttribute>())
                                         .Where(jp => jp != null)
                                         .Select(jp => jp.PropertyName);
    
    string propsList = string.Join(',', props);
    
    0 讨论(0)
  • 2020-12-10 12:33

    In cases where the model is only partially annotated with [JsonProperty(PropertyName = "XXX")] attributes, or is annotated with data contract attributes, or has ignored properties, you can use Json.NET's own contract resolver to obtain the list of serialized property names. First, introduce the following extension method:

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

    Then, do:

    // 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);
    

    For resolver use CamelCasePropertyNamesContractResolver if you are camel casing your property names (which ASP.NET Core Web API does by default); otherwise use DefaultContractResolver.

    Sample fiddle.

    0 讨论(0)
  • 2020-12-10 12:47

    @Leigh Shepperson has the right idea; however, you can do it with less code using LINQ. I would create a helper method like this:

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

    You can use it like this:

    var fields = "&fields=" + GetFields(typeof(model));
    

    EDIT

    If you're running under the 3.5 version of the .Net Framework such that you don't have the generic GetCustomAttribute<T> method available to you, you can do the same thing with the non-generic GetCustomAttributes() method instead, using it with SelectMany and Cast<T>:

        return string.Join(",",
            modelType.GetProperties()
                     .SelectMany(p => p.GetCustomAttributes(typeof(JsonPropertyAttribute))
                                       .Cast<JsonPropertyAttribute>())
                     .Select(jp => jp.PropertyName)
                     .ToArray());
    
    0 讨论(0)
  • 2020-12-10 12:49

    You can do this using reflection. This is the general idea:

    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;
                    }
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题