Si j'ai une classe de modèle C # qui est utilisée par JSON.net pour lier des données à partir d'une chaîne JSON sérialisée, existe-t-il un moyen de créer une chaîne de requête à partir de cette classe afin de faire la demande initiale?
Exemple de classe de modèle:
public class model
{
[JsonProperty(PropertyName = "id")]
public long ID { get; set; }
[JsonProperty(PropertyName = "some_string")]
public string SomeString {get; set;}
}
Exemple de chaîne de requête:
baseUrl + uri + "&fields=id,some_string" + token
Donc l'essentiel de ce que j'essaie de faire est de rassembler à la fois "id" et "some_string" à partir de l'objet modèle afin que je puisse créer dynamiquement les arguments "& fields". Merci!
@Leigh Shepperson a la bonne idée; cependant, vous pouvez le faire avec moins de code en utilisant LINQ. Je créerais une méthode d'aide comme celle-ci:
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));
}
Vous pouvez l'utiliser comme ceci:
var fields = "&fields=" + GetFields(typeof(model));
MODIFIER
Si vous utilisez la version 3.5 du .Net Framework de manière à ne pas disposer de la méthode générique GetCustomAttribute<T>
, Vous pouvez faire la même chose avec la méthode non générique GetCustomAttributes()
à la place, en l'utilisant avec SelectMany
et Cast<T>
:
return string.Join(",",
modelType.GetProperties()
.SelectMany(p => p.GetCustomAttributes(typeof(JsonPropertyAttribute))
.Cast<JsonPropertyAttribute>())
.Select(jp => jp.PropertyName)
.ToArray());
Vous pouvez le faire en utilisant la réflexion. C'est l'idée générale:
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;
}
}
}
}
}
Dans les cas où le modèle n'est que partiellement annoté avec des attributs [JsonProperty(PropertyName = "XXX")]
, ou est annoté avec attributs de contrat de données , ou a ignoré propriétés, vous pouvez utiliser Json Propre .NET résolveur de contrat pour obtenir la liste des noms de propriété sérialisés. Tout d'abord, introduisez la méthode d'extension suivante:
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();
}
}
Alors fais:
// 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);
Pour resolver
utilisez CamelCasePropertyNamesContractResolver
si vous mettez des chameaux dans les noms de vos propriétés (ce que fait l'API Web ASP.NET Core par défaut ); sinon utilisez DefaultContractResolver
.
Exemple violon .
Une petite variante de la solution @Brian Rogers qui résout le problème des exceptions nulles:
IEnumerable<string> props = typeof(T).GetProperties()
.Select(p => p.GetCustomAttribute<JsonPropertyAttribute>())
.Where(jp => jp != null)
.Select(jp => jp.PropertyName);
string propsList = string.Join(',', props);