Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

316
Vistas
Analizando tanto la matriz como el objeto único

La API volvió a ajustar el objeto json como debajo de 2 formularios.

Formulario 1

 { "Pricing": [ { "total": 27, "currency": "USD", "charges": [ //Chargers Array { "code": "C1", "currency": "USD", "rate": 15 }, { "code": "C45", "currency": "USD", "rate": 12 } ] } ] }

Formulario 2

 { "Pricing": [ { "total": 12, "currency": "USD", "charges": { //Chargers single object "code": "C1", "currency": "USD", "rate": 12 } } ] }

Como puede ver, a veces los objetos de los cargadores regresan con la matriz y otras veces no. Mi pregunta es ¿cómo analizar esto en un objeto de clase C#? Si agregué la clase C # como se muestra a continuación, no se puede analizar correctamente para el Formulario 2. (El formulario 1 se analiza correctamente)

 public class Charge { public string code { get; set; } public string currency { get; set; } public decimal rate { get; set; } } public class Pricing { public decimal total { get; set; } public string currency { get; set; } public List<Charge> charges { get; set; } //In Form 2, this should be single object } public class MainObj { public List<Pricing> Pricing { get; set; } }

Se produjo un error al analizar con la deserialización de Newtonsoft.

 MainObj obj = JsonConvert.DeserializeObject<MainObj>(json);

Error

No se puede deserializar el objeto JSON actual (por ejemplo, {"nombre":"valor"}) en el tipo 'System.Collections.Generic.List`1[Charge]' porque el tipo requiere una matriz JSON (por ejemplo, [1,2,3] ) para deserializar correctamente. Para corregir este error, cambie el JSON a una matriz JSON (por ejemplo, [1,2,3]) o cambie el tipo deserializado para que sea un tipo .NET normal (por ejemplo, no un tipo primitivo como un entero, no un tipo de colección como una matriz o lista) que se puede deserializar desde un objeto JSON. JsonObjectAttribute también se puede agregar al tipo para obligarlo a deserializarse de un objeto JSON. Ruta 'Pricing[0].charges.code', línea 1, posición 69.

¿Algún método común para analizar, al recibir diferentes tipos de objetos con C#?

(También analicé esto , pero es para Java. Y la mayoría de este tipo de preguntas se plantearon para Java pero no para C#).

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Podría optar por un enfoque para intentar analizar el objeto de Form1 en json, si falla, usará el objeto de Form2 en json.

Ejemplo aquí y abajo: https://dotnetfiddle.net/F1Yh25

 using System; using System.Collections.Generic; using Newtonsoft.Json; public class Program { public static void Main() { string form1 = "{\"Pricing\":[{\"total\":27,\"currency\":\"USD\",\"charges\":[{\"code\":\"C1\",\"currency\":\"USD\",\"rate\":15},{\"code\":\"C45\",\"currency\":\"USD\",\"rate\":12}]}]}"; string form2 = "{\"Pricing\":[{\"total\":12,\"currency\":\"USD\",\"charges\":{\"code\":\"C1\",\"currency\":\"USD\",\"rate\":12}}]}"; string json = form1;//Change form1 to form2 and it will also work try { Form1.Root Object = JsonConvert.DeserializeObject<Form1.Root>(json); Console.WriteLine("Item 1's Pricing: " + Object.Pricing[0].total); } catch//If Form1's json is Form2 it will catch here { Form2.Root Object = JsonConvert.DeserializeObject<Form2.Root>(json); Console.WriteLine("Item 1's Pricing: " + Object.Pricing[0].total); } } public class Form1 { public class Charge { public string code { get; set; } public string currency { get; set; } public int rate { get; set; } } public class Pricing { public int total { get; set; } public string currency { get; set; } public List<Charge> charges { get; set; } } public class Root { public List<Pricing> Pricing { get; set; } } } public class Form2 { public class Charges { public string code { get; set; } public string currency { get; set; } public int rate { get; set; } } public class Pricing { public int total { get; set; } public string currency { get; set; } public Charges charges { get; set; } } public class Root { public List<Pricing> Pricing { get; set; } } } }
over 4 years ago · Santiago Trujillo Denunciar

0

Ok, aquí hay otra forma de hacer esto sin tener que usar dos clases y sin tener que intentar atrapar. Básicamente, solo actualice la clase de precios a la siguiente y funciona para ambos casos. Probablemente sea una mejor manera, pero esto es mejor (al menos en mi opinión) y tener dos clases y tratar de atrapar tu bifurcación. Si tuviera diez propiedades con este problema, ¿crearía 10? clases para manejar cada combo? De ninguna manera jaja!

 public class Pricing { public int total { get; set; } public string currency { get; set; } private List<Charge> _charges; public object charges { get { return _charges; } set { if(value.GetType().Name == "JArray") { _charges = JsonConvert.DeserializeObject<List<Charge>>(value.ToString()); } else { _charges = new List<Charge>(); var charge = JsonConvert.DeserializeObject<Charge>(value.ToString()); _charges.Add(charge); } } } }
over 4 years ago · Santiago Trujillo Denunciar

0

Otra forma de lidiar con este problema es definir un JsonConverter personalizado que pueda manejar ambos casos.

 class ArrayOrObjectConverter<T> : JsonConverter { public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var token = JToken.Load(reader); return token.Type == JTokenType.Array ? token.ToObject<List<T>>() : new List<T> { token.ToObject<T>() }; } public override bool CanConvert(Type objectType) => objectType == typeof(List<T>); public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) =>throw new NotImplementedException(); }
  • Dentro del ReadJson primero obtenemos un JToken para poder determinar el Type (tipo) del valor de lectura
    • En base a eso, podemos llamar a ToObject<List<T>> o ToObject<T>
  • Dentro de CanConvert , examinamos que el tipo de propiedad que se va a completar es List<T>
    • Aunque hay un JsonConverter<T> genérico en el que no tiene que definir el CanConvert , su ReadJson se puede implementar de una manera un poco más complicada.
  • Dado que la pregunta tiene que ver con la deserialización, no he implementado el método WriteJson
    • También puede considerar anular la propiedad CanWrite de la clase base para que siempre devuelva false

Con esta clase en nuestra mano, puede decorar sus propiedades con un JsonConverterAttribute para decirle a Json.NET cómo tratar con esas propiedades.

 public class Pricing { public decimal total { get; set; } public string currency { get; set; } [JsonConverter(typeof(ArrayOrObjectConverter<Charge>))] public List<Charge> charges { get; set; } ... }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda