none
String JSON a Objeto RRS feed

  • Pregunta

  • Hola, obtengo un JSON de un WebService con este formato:

    {
        "1": {
            "nombre" : "ejemplo",
            "usuario" : "ejemploUsuario"
        },
    
        "2": {
            "nombre" : "ejemplo2",
            "usuario" : "ejemploUsuario2"
        }
    }

    He intentado convertirlos a objetos de la siguiente forma...


    - Con las clases:

        public class Usuarios
        {
            public List<Usuario> ListaUsuarios{ get; set; }
        }
    
        public class Usuario
        {
            [JsonProperty("nombre")]
            public string Nombre
            {
                get;
                set;
            }
    
            [JsonProperty("usuario")]
            public string Usuario
            {
                get;
                set;
            }
        }

    Hago uso de Newtonsoft.Json:

    string jsonDataString; // aqui va el json con el formato que puse arriba

    Usuarios usuarios = JsonConvert.DeserializeObject<Usuarios>(jsonDataString);


    Sin embargo, cuando trato de acceder al atributo "ListaUsuarios" de la variable "usuarios" de arriba, aparece como NULL la lista.

    Tengo algún error? o habrá otra forma de hacerlo?



    Ian Alexandro

    jueves, 14 de marzo de 2019 19:23

Respuestas

  • Hola, cuando en un JSON te devuelven elementos que son numéricos se deben deserializar a Dictionary ya que ningún lenguaje de la plataforma .NET te permite crear una clase cuyo nombre sea un número.

    Te recomiendo eches un ojo a esta página para generar tus clases serializables QuickType

    Usando tu texto Json y generando las clases tenemos un ejemplo así

    // <auto-generated />
    //
    // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
    //
    //    using QuickType;
    //
    //    var welcome = Welcome.FromJson(jsonString);
    
    namespace QuickType
    {
        using System;
        using System.Collections.Generic;
    
        using System.Globalization;
        using Newtonsoft.Json;
        using Newtonsoft.Json.Converters;
    
        public partial class Welcome
        {
            [JsonProperty("nombre")]
            public string Nombre { get; set; }
    
            [JsonProperty("usuario")]
            public string Usuario { get; set; }
        }
    
        public partial class Welcome
        {
            public static Dictionary<string, Welcome> FromJson(string json) => JsonConvert.DeserializeObject<Dictionary<string, Welcome>>(json, QuickType.Converter.Settings);
        }
    
        public static class Serialize
        {
            public static string ToJson(this Dictionary<string, Welcome> self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
        }
    
        internal static class Converter
        {
            public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
            {
                MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
                DateParseHandling = DateParseHandling.None,
                Converters =
                {
                    new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
                },
            };
        }
    }
    

    Cambia los namespaces y el nombre de la clase obviamente.

    El ejemplo que se indica para deserialziar es así

    var welcome = Welcome.FromJson(jsonString);


    Si se solucionó tu consulta no olvides marcar la respuesta. Si te ayudó, vótala como útil. Saludos

    jueves, 14 de marzo de 2019 21:11
    Moderador

Todas las respuestas

  • hola

    la unica forma de parsear cuando definen propiedades de forma variable es con el JObject y acceder a las propiedades, como en este ejemplo

     string json = @"{
                            '-LWOV1O6vcehVv4AhTQr': {
                                'password': '123456',
                                'user': 'juana',
                                'website': 'www.juana.com'
                            },
                            '-LWOV2VTAhMRhRygK0nZ': {
                                'password': '123456',
                                'user': 'Andrea',
                                'website': 'www.andrea.com'
                            }
                            }";
    
            JObject jObj = JObject.Parse(json);
    
            var result = from item in jObj.Properties()
                         select new LoginDataResponse(){
                             Password = item.Value["password"].ToString(),
                             User = item.Value["user"].ToString(),
                             Website = item.Value["website"].ToString()
                         };
    
            foreach(var item in result)
            {
                Console.WriteLine("{0}, {1}, {2}", item.User, item.Password, item.Website);
            }

    no se puede deserializar directo a una clase, lo haces en el select del linq

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 14 de marzo de 2019 20:59
  • Hola, cuando en un JSON te devuelven elementos que son numéricos se deben deserializar a Dictionary ya que ningún lenguaje de la plataforma .NET te permite crear una clase cuyo nombre sea un número.

    Te recomiendo eches un ojo a esta página para generar tus clases serializables QuickType

    Usando tu texto Json y generando las clases tenemos un ejemplo así

    // <auto-generated />
    //
    // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
    //
    //    using QuickType;
    //
    //    var welcome = Welcome.FromJson(jsonString);
    
    namespace QuickType
    {
        using System;
        using System.Collections.Generic;
    
        using System.Globalization;
        using Newtonsoft.Json;
        using Newtonsoft.Json.Converters;
    
        public partial class Welcome
        {
            [JsonProperty("nombre")]
            public string Nombre { get; set; }
    
            [JsonProperty("usuario")]
            public string Usuario { get; set; }
        }
    
        public partial class Welcome
        {
            public static Dictionary<string, Welcome> FromJson(string json) => JsonConvert.DeserializeObject<Dictionary<string, Welcome>>(json, QuickType.Converter.Settings);
        }
    
        public static class Serialize
        {
            public static string ToJson(this Dictionary<string, Welcome> self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
        }
    
        internal static class Converter
        {
            public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
            {
                MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
                DateParseHandling = DateParseHandling.None,
                Converters =
                {
                    new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
                },
            };
        }
    }
    

    Cambia los namespaces y el nombre de la clase obviamente.

    El ejemplo que se indica para deserialziar es así

    var welcome = Welcome.FromJson(jsonString);


    Si se solucionó tu consulta no olvides marcar la respuesta. Si te ayudó, vótala como útil. Saludos

    jueves, 14 de marzo de 2019 21:11
    Moderador
  • Hola Leandro, gracias por responder, no tuve la posibilidad de probar tu solución debido a que manejo .NET 3.5, por lo tanto, estoy usando un dll de Newtonsoft.Json para la versión 3.5 de .NET


    Ian Alexandro

    martes, 19 de marzo de 2019 19:28
  • Hola Sergio, gracias por responder, diste en el clavo, y lo solucioné así:


    JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
    
    ICollection usuariosCollection = (ICollection)javaScriptSerializer.DeserializeObject(jsonString);
    
    foreach (KeyValuePair<string, object> u in usuariosCollection )
    {
            string jsonUsuario = JsonConvert.SerializeObject(u.Value);
            Usuario usuario = JsonConvert.DeserializeObject<Usuario >(jsonUsuario);
    }

    Gracias!



    Ian Alexandro

    martes, 19 de marzo de 2019 19:33