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