Convertir cadena JSON a objeto C #

183

Intentando convertir una cadena JSON en un objeto en C #. Usando un caso de prueba realmente simple:

JavaScriptSerializer json_serializer = new JavaScriptSerializer();
object routes_list = json_serializer.DeserializeObject("{ \"test\":\"some data\" }");

El problema es que routes_list nunca se establece; Es un objeto indefinido. ¿Algunas ideas?

Justin
fuente
1
@Greg: Realmente recomiendo la JavaScriptSerializerversión sobre MS, ya que no aceptará nada más que el formato JSON personalizado de WCF (por ejemplo, los campos de fecha que parecen fechas pero no están rodeados en DATE () fallan miserablemente)
Brad Christie
Además, mire este análisis de objetos JSON con JavascriptSerializer en el artículo de .NET , que en realidad es un gran tutorial.
scatmoi
¿Dónde obtienes JavaScriptSerializer? No se reconoce en mi proyecto C # .NET 3.5.
B. Clay Shannon
1
@SI. Clay Shannon Esto lo resolvió para mí stackoverflow.com/questions/7000811/…
Fuzzybear

Respuestas:

127

Parece que estás tratando de deserializar a un objeto sin procesar. Puede crear una clase que represente el objeto al que está convirtiendo. Esto sería más útil en los casos en que se trata de objetos más grandes o cadenas JSON.

Por ejemplo:

  class Test {

      String test; 

      String getTest() { return test; }
      void setTest(String test) { this.test = test; }

  }

Entonces su código de deserialización sería:

   JavaScriptSerializer json_serializer = new JavaScriptSerializer();
   Test routes_list = 
          (Test)json_serializer.DeserializeObject("{ \"test\":\"some data\" }");

Se puede encontrar más información en este tutorial: http://www.codeproject.com/Tips/79435/Deserialize-JSON-with-Csharp.aspx

jmort253
fuente
1
Pero en el artículo puntiagudo se utilizan autopropertías. Vale la pena mencionar también.
Ivan Kochurkin
11
Lo sentimos, pero este ejemplo de código no funciona. DeserializeObject da una excepción. Utilice var routes_list = serializer. Deserialize <Test> ("{\" test \ ": \" some data \ "}"); en lugar. Además, no necesita get / setTest (), y la prueba de cadena debe ser pública. Esto se parece más a Java que a C #.
dvallejo
Como Dan Vallejo mencionó, esta es una solución incorrecta. Después de todo, setTest (prueba de cadena) no regresa, lo que también es un error de compilación.
Payam
1
También puede usar esto: json_serializer.Deserialize <Test> ("{\" test \ ": \" some data \ "}"); // en lugar de (Prueba) json_serializer .....
Bashar Abu Shamaa
1
Si no está seguro del formato para su objeto de clase, pruebe este enlace . Traduce su cadena Json en las clases correctas. ¡Me ahorró un montón de tiempo!
jade290
231

O puede usar la biblioteca Newtownsoft.Json de la siguiente manera:

using Newtonsoft.Json;
...
var result = JsonConvert.DeserializeObject<T>(json);

¿Dónde Testá su tipo de objeto que coincide con su cadena JSON?

tripletdad99
fuente
3
Es muy fácil y pensé mucho sobre cómo hacer esto.
maracuja-juice
58

Probablemente no quiera declarar rutas_lista como un object tipo. No tiene una propiedad .test, por lo que realmente no va a recuperar un buen objeto. Este es uno de esos lugares donde sería mejor definir una clase o una estructura, o hacer uso de la palabra clave dinámica.

Si realmente desea que este código funcione como lo tiene, necesitará saber que el objeto devuelto por DeserializeObject es un diccionario genérico de cadena, objeto. Aquí está el código para hacerlo de esa manera:

var json_serializer = new JavaScriptSerializer();
var routes_list = (IDictionary<string, object>)json_serializer.DeserializeObject("{ \"test\":\"some data\" }");
Console.WriteLine(routes_list["test"]);

Si desea utilizar la palabra clave dinámica, puede leer cómo aquí .

Si declara una clase o estructura, puede llamar a Deserialize en lugar de DeserializeObject de la siguiente manera:

class MyProgram {
    struct MyObj {
        public string test { get; set; }
    }

    static void Main(string[] args) {
        var json_serializer = new JavaScriptSerializer();
        MyObj routes_list = json_serializer.Deserialize<MyObj>("{ \"test\":\"some data\" }");
        Console.WriteLine(routes_list.test);

        Console.WriteLine("Done...");
        Console.ReadKey(true);
    }
}
mattmc3
fuente
Haciendo: json_serializer = new JavaScriptSerializer (); object routes_list = (IDictionary <cadena, objeto>) json_serializer.DeserializeObject ("{\" test \ ": \" algunos datos aquí \ "}"); Todavía obtener 'routes_list' no existe en el contexto actual.
Justin
1
No utilice object routes_list. Use varo repítase explícitamente y declare routes_list como IDictionary <string, object>.
mattmc3
31

Uso de objetos dinámicos con JavaScriptSerializer.

JavaScriptSerializer serializer = new JavaScriptSerializer(); 
dynamic item = serializer.Deserialize<object>("{ \"test\":\"some data\" }");
string test= item["test"];

//test Result = "some data"
İbrahim Özbölük
fuente
19

Newtonsoft es más rápido que el serializador de scripts Java. ... este depende del paquete Newtonsoft NuGet, que es popular y mejor que el serializador predeterminado.

solución de código de una línea.

var myclass = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(Jsonstring);

Myclass oMyclass = Newtonsoft.Json.JsonConvert.DeserializeObject<Myclass>(Jsonstring);
MSTdev
fuente
15

Aquí hay una clase simple que improvisé en varias publicaciones ... Se ha probado durante unos 15 minutos, pero parece funcionar para mis propósitos. Se utiliza JavascriptSerializerpara hacer el trabajo, al que se puede hacer referencia en su aplicación utilizando la información detallada en esta publicación .

El siguiente código se puede ejecutar en LinqPad para probarlo:

  • Haga clic derecho en la pestaña de su script en LinqPad y seleccione "Propiedades de consulta"
  • Hacer referencia al "System.Web.Extensions.dll" en "Referencias adicionales"
  • Agregar una "Importación de espacio de nombres adicional" de "System.Web.Script.Serialization".

¡Espero eso ayude!

void Main()
{
  string json = @"
  {
    'glossary': 
    {
      'title': 'example glossary',
        'GlossDiv': 
        {
          'title': 'S',
          'GlossList': 
          {
            'GlossEntry': 
            {
              'ID': 'SGML',
              'ItemNumber': 2,          
              'SortAs': 'SGML',
              'GlossTerm': 'Standard Generalized Markup Language',
              'Acronym': 'SGML',
              'Abbrev': 'ISO 8879:1986',
              'GlossDef': 
              {
                'para': 'A meta-markup language, used to create markup languages such as DocBook.',
                'GlossSeeAlso': ['GML', 'XML']
              },
              'GlossSee': 'markup'
            }
          }
        }
    }
  }

  ";

  var d = new JsonDeserializer(json);
  d.GetString("glossary.title").Dump();
  d.GetString("glossary.GlossDiv.title").Dump();  
  d.GetString("glossary.GlossDiv.GlossList.GlossEntry.ID").Dump();  
  d.GetInt("glossary.GlossDiv.GlossList.GlossEntry.ItemNumber").Dump();    
  d.GetObject("glossary.GlossDiv.GlossList.GlossEntry.GlossDef").Dump();   
  d.GetObject("glossary.GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso").Dump(); 
  d.GetObject("Some Path That Doesnt Exist.Or.Another").Dump();   
}


// Define other methods and classes here

public class JsonDeserializer
{
  private IDictionary<string, object> jsonData { get; set; }

  public JsonDeserializer(string json)
  {
    var json_serializer = new JavaScriptSerializer();

    jsonData = (IDictionary<string, object>)json_serializer.DeserializeObject(json);
  }

  public string GetString(string path)
  {
    return (string) GetObject(path);
  }

  public int? GetInt(string path)
  {
    int? result = null;

    object o = GetObject(path);
    if (o == null)
    {
      return result;
    }

    if (o is string)
    {
      result = Int32.Parse((string)o);
    }
    else
    {
      result = (Int32) o;
    }

    return result;
  }

  public object GetObject(string path)
  {
    object result = null;

    var curr = jsonData;
    var paths = path.Split('.');
    var pathCount = paths.Count();

    try
    {
      for (int i = 0; i < pathCount; i++)
      {
        var key = paths[i];
        if (i == (pathCount - 1))
        {
          result = curr[key];
        }
        else
        {
          curr = (IDictionary<string, object>)curr[key];
        }
      }
    }
    catch
    {
      // Probably means an invalid path (ie object doesn't exist)
    }

    return result;
  }
}
Brad Parks
fuente
14

Puede cumplir su requisito fácilmente utilizando la biblioteca Newtonsoft.Json. Estoy escribiendo el siguiente ejemplo para echarle un vistazo.

Clase para el tipo de objeto que recibe:

public class User
{
    public int ID { get; set; }
    public string Name { get; set; }

}

Código:

static void Main(string[] args)
{

      string json = "{\"ID\": 1, \"Name\": \"Abdullah\"}";

      User user = JsonConvert.DeserializeObject<User>(json);

      Console.ReadKey();
}

Esta es una manera muy simple de analizar su json.

Mirza Danish Baig
fuente
11

Como dijo tripletdad99

var result = JsonConvert.DeserializeObject<T>(json);

pero si usted no desea crear un objeto adicional, puede hacerlo con Dictionarysu lugar

var result = JsonConvert.DeserializeObject<Dictionary<string, string>>(json_serializer);
stanimirsp
fuente
Esto es útil, cuando luego pasa parámetros a Url.Action (acción, controlador, resultado)
Lapenkov Vladimir
8

agregue este ddl para hacer referencia a su proyecto: System.Web.Extensions.dll

use este espacio de nombres: using System.Web.Script.Serialization;

public class IdName
{
    public int Id { get; set; }
    public string Name { get; set; }
}


   string jsonStringSingle = "{'Id': 1, 'Name':'Thulasi Ram.S'}".Replace("'", "\"");
   var entity = new JavaScriptSerializer().Deserialize<IdName>(jsonStringSingle);

   string jsonStringCollection = "[{'Id': 2, 'Name':'Thulasi Ram.S'},{'Id': 2, 'Name':'Raja Ram.S'},{'Id': 3, 'Name':'Ram.S'}]".Replace("'", "\"");
   var collection = new JavaScriptSerializer().Deserialize<IEnumerable<IdName>>(jsonStringCollection);
Tulasiram
fuente
6

Copie su Json y péguelo en el cuadro de texto en json2csharp y haga clic en el botón Generar.

Se generará una clase cs usando ese archivo cs como se muestra a continuación

var generatedcsResponce = JsonConvert.DeserializeObject(yourJson);

¿Dónde RootObjectestá el nombre del archivo cs generado ?

islam
fuente
4

Otra forma rápida y fácil de semiautomatizar estos pasos es:

  1. tome el JSON que desea analizar y péguelo aquí: https://app.quicktype.io/ . Cambie el idioma a C # en el menú desplegable.
  2. Actualice el nombre en la parte superior izquierda a su nombre de clase, por defecto es "Bienvenido".
  3. En Visual Studio, vaya a Sitio web -> Administrar paquetes y use NuGet para agregar Json.Net desde Newtonsoft.
  4. app.quicktype.io generó métodos de serialización basados ​​en Newtonsoft. Alternativamente, ahora puede usar código como:

    Cliente WebClient = nuevo Cliente Web ();

    string myJSON = client.DownloadString (" https://URL_FOR_JSON.com/JSON_STUFF ");

    var myClass = Newtonsoft.Json.JsonConvert.DeserializeObject (myJSON);

Jason Hitchings
fuente
Enlace ya no es válido
Myles J
Gracias Myles J, actualicé a un nuevo sitio que parece funcionar bien.
Jason Hitchings
0

Convierta una cadena JSON en un objeto en C #. Usando el siguiente caso de prueba ... funcionó para mí. Aquí " MenuInfo " es mi objeto de clase C #.

JsonTextReader reader = null;
try
{
    WebClient webClient = new WebClient();
    JObject result = JObject.Parse(webClient.DownloadString("YOUR URL"));
    reader = new JsonTextReader(new System.IO.StringReader(result.ToString()));
    reader.SupportMultipleContent = true;
}
catch(Exception)
{}

JsonSerializer serializer = new JsonSerializer();
MenuInfo menuInfo = serializer.Deserialize<MenuInfo>(reader);
Bhaskar
fuente
0

Primero debes incluir una biblioteca como:

using System.Runtime.Serialization.Json;

DataContractJsonSerializer desc = new DataContractJsonSerializer(typeof(BlogSite));
string json = "{\"Description\":\"Share knowledge\",\"Name\":\"zahid\"}";

using (var ms = new MemoryStream(ASCIIEncoding.ASCII.GetBytes(json)))
{
    BlogSite b = (BlogSite)desc.ReadObject(ms);
    Console.WriteLine(b.Name);
    Console.WriteLine(b.Description);
}
Muhammad Zahid
fuente