restresponse jsonconvert example deserialize consume c# restsharp

c# - jsonconvert - Deserializar dinĂ¡micamente a una propiedad en RestSharp



restsharp github (2)

Estoy jugando con Harvest API y estoy tratando de mapear automáticamente las entidades de la forma más fácil posible, desafortunadamente cuando hago una solicitud como GET /projects , genera un resultado como este:

[{ project: { name: "Test" } }, { project: { name: "Test 2" }]

En RestSharp, no puedo hacer esto directamente:

client.Execute<List<Project>>(request)

Porque va a buscar una propiedad llamada Project . Así que tengo que hacer otra clase que tenga esa propiedad, y llamarlo así:

client.Execute<List<ProjectContainer>>(request)

No quiero hacer una clase ''contenedor'' para cada entidad, así que pensé que encontré una solución inteligente para hacer una clase que puedo usar en todos:

public class ListContainer<T> where T : IHarvestEntity { public T Item { get; set; } }

Pero, por supuesto, el deserializador no tiene idea de que necesita asignar el nombre de la entidad (o "Proyecto") a la propiedad Item . En la documentación de restsharp encontré que podría usar [DeserializeAs(Name = "CustomProperty")] para indicar al deserializador qué campo asignar a esta propiedad. Sin embargo, los atributos solo permiten constantes, lo que significa que no puedo hacer:

[DeserializeAs(Name = typeof(T).FullName)] public T Item { get; set; }

¿Alguien sabe una solución inteligente a esto? ¿Entonces no tengo que crear 10 clases de contenedores diferentes?


Para que sea realmente simple, puede usar List<dynamic> y acceder a la propiedad / propiedades por nombre con una sola línea.

var names = client.Execute<List<dynamic>>(request).Data.Select( item => item["project"]["name"]).ToList(); // list of names

Si esto no es suficiente, entonces podría improvisar su propio asignador y extraer una colección de, por ejemplo Project instancias del Project :

var projects = client.Execute<List<dynamic>>(request).Data.Select( item => Map<Project>(item)).ToList(); // list of Project instances

donde el método de Map podría ser algo así como

public T Map<T>(dynamic item) where T : class { // inline for clarity var mappings = new Dictionary<Type,Func<dynamic,object>> { { typeof(Project), map => new Project(map["project"]["name"]) } }; return (T)mappings[typeof(T)].Invoke(item); }

Project dado se define como

public class Project { public Project(string name) { Name = name; } public string Name { get; set; } }


Te sugiero que uses el equivalente de XPath para Json. Con Json.NET puedes parse la cadena y crear un objeto dinámico.

Con SelectToken puedes consultar valores, o usar Linq .

El código se ve algo como esto (no lo probé):

// execute the request RestResponse response = client.Execute(request); var content = response.Content; // raw content as string JObject o = JObject.Parse(content); IList<string> projectNames = o.SelectToken("project").Select(s => (string)s.name).ToList();

Puede codificar las rutas o configurar las rutas que desee.

--- Editar ---

Aquí hay un ejemplo que probé, convirtiendo la cadena json en una lista de proyectos.

var projects = JArray.Parse(response.Content).Select(r => new Project(r["project"]["name"].Value<string>())).ToList();