Converter string JSON em objeto de C #

183

Tentando converter uma sequência JSON em um objeto em C #. Usando um caso de teste realmente simples:

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

O problema é que o routes_list nunca é definido; é um objeto indefinido. Alguma ideia?

Justin
fonte
1
@ Greg: Eu realmente recomendo o JavaScriptSerializersobre a versão do MS, pois não irá aceitar qualquer outra coisa, mas do WCF personalizado formatação JSON (por exemplo, campos de data que se parecem com datas, mas não são cercados em DATE () falhar miseravelmente)
Brad Christie
Além disso, veja este artigo Analisando objetos JSON com JavascriptSerializer no .NET , que é realmente um ótimo tutorial.
scatmoi
Onde você está obtendo o JavaScriptSerializer? Ele não é reconhecido no meu projeto do C # .NET 3.5.
B. Clay Shannon
1
@B. Argila Shannon Este resolvido para mim stackoverflow.com/questions/7000811/...
Fuzzybear

Respostas:

127

Parece que você está tentando desserializar para um objeto bruto. Você pode criar uma classe que representa o objeto para o qual está convertendo. Isso seria mais útil nos casos em que você está lidando com objetos maiores ou Strings JSON.

Por exemplo:

  class Test {

      String test; 

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

  }

Então seu código de desserialização seria:

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

Mais informações podem ser encontradas neste tutorial: http://www.codeproject.com/Tips/79435/Deserialize-JSON-with-Csharp.aspx

jmort253
fonte
1
Porém, no artigo apontado, são utilizadas autopropiedades. Também vale a pena mencionar.
Ivan Kochurkin
11
Desculpe, mas este exemplo de código não funciona. DeserializeObject fornece uma exceção. Use var routes_list = serializer.Deserialize <Test> ("{\" test \ ": \" some data \ "}"); em vez de. Além disso, você não precisa de get / setTest () e String test, deve ser público. Parece mais java que c #.
Dvallejo 8/10
como Dan Vallejo mencionou, esta é uma solução incorreta. Afinal, setTest (String test) não está retornando, o que também é um erro de compilação.
Payam
1
Também pode usar isso: json_serializer.Deserialize <Test> ("{\" test \ ": \" some data \ "}"); // em vez de (Test) json_serializer .....
Bashar Abu Shamaa
1
Se você não tiver certeza do formato do seu objeto de classe, tente este link . Ele converte sua string Json nas classes corretas. Economizou-me uma tonelada de tempo!
Jade290
231

Ou, você pode usar a biblioteca Newtownsoft.Json da seguinte maneira:

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

Onde Testá o seu tipo de objeto que corresponde à sua sequência JSON.

tripletdad99
fonte
3
É tão fácil e pensei tanto em como fazer isso.
Maracuja-juice
58

Você provavelmente não deseja apenas declarar routes_list como um object tipo. Ele não possui uma propriedade .test, então você realmente não receberá um bom objeto de volta. Este é um daqueles lugares em que seria melhor definir uma classe ou uma estrutura ou usar a palavra-chave dinâmica.

Se você realmente deseja que esse código funcione como você o possui, você precisará saber que o objeto retornado por DeserializeObject é um dicionário genérico de string, objeto. Aqui está o código para fazer dessa maneira:

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

Se você deseja usar a palavra-chave dinâmica, pode ler como aqui .

Se você declarar uma classe ou estrutura, poderá chamar Deserialize em vez de DeserializeObject da seguinte maneira:

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
fonte
Fazendo: json_serializer = new JavaScriptSerializer (); objeto routes_list = (IDictionary <string, objeto>) json_serializer.DeserializeObject ("{\" test \ ": \" alguns dados aqui \ "}"); Ainda a obtenção de 'routes_list' não existe no contexto atual.
Justin
1
Não use object routes_list. Use varou repita-se explicitamente e declare routes_list como um IDictionary <string, objeto>.
mattmc3
31

Usando objeto dinâmico com 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
fonte
19

Newtonsoft é mais rápido que o serializador de scripts java. ... esse depende do pacote Newtonsoft NuGet, que é popular e melhor que o serializador padrão.

solução de código de uma linha.

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

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

Aqui está uma classe simples que eu juntei de várias postagens ... Foi testada por cerca de 15 minutos, mas parece funcionar para meus propósitos. Ele usa JavascriptSerializerpara fazer o trabalho, que pode ser referenciado no seu aplicativo usando as informações detalhadas nesta postagem .

O código abaixo pode ser executado no LinqPad para testá-lo:

  • Clique com o botão direito do mouse na guia Script no LinqPad e escolha "Query Properties"
  • Referenciando o "System.Web.Extensions.dll" em "Referências adicionais"
  • Adicionando um "Importação de espaço para nome adicional" de "System.Web.Script.Serialization".

Espero que ajude!

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
fonte
14

Você pode atender facilmente aos seus requisitos usando a biblioteca Newtonsoft.Json. Estou escrevendo o exemplo abaixo e dê uma olhada nele.

Classe para o tipo de objeto que você recebe:

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();
}

Essa é uma maneira muito simples de analisar seu json.

Mirza Danish Baig
fonte
11

Como disse tripletdad99

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

mas se você não quiser criar um objeto extra que você pode fazê-lo com Dictionaryvez

var result = JsonConvert.DeserializeObject<Dictionary<string, string>>(json_serializer);
stanimirsp
fonte
Isso é útil, quando você passa os parâmetros para Url.Action (ação, controlador, resultado)
Lapenkov Vladimir 23/04
8

adicione este ddl para fazer referência ao seu projeto: System.Web.Extensions.dll

use este espaço para nome: 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);
Thulasiram
fonte
6

Copie seu Json e cole na caixa de texto em json2csharp e clique no botão Gerar.

Uma classe cs será gerada usando esse arquivo cs como abaixo

var generatedcsResponce = JsonConvert.DeserializeObject(yourJson);

Onde RootObjecté o nome do arquivo cs gerado ;

islamismo
fonte
4

Outra maneira rápida e fácil de semi-automatizar essas etapas é:

  1. pegue o JSON que você deseja analisar e cole-o aqui: https://app.quicktype.io/ . Mude o idioma para C # no menu suspenso.
  2. Atualize o nome no canto superior esquerdo para o nome da sua classe; o padrão é "Bem-vindo".
  3. No visual studio, acesse Site -> Gerenciar pacotes e use o NuGet para adicionar o Json.Net da Newtonsoft.
  4. app.quicktype.io gerou métodos de serialização com base no Newtonsoft. Como alternativa, agora você pode usar código como:

    Cliente WebClient = novo WebClient ();

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

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

Jason Hitchings
fonte
O link não é mais válido
Myles J
Obrigado Myles J, atualizei para um novo site que parece funcionar bem.
Jason Hitchings
0

Converta uma string JSON em um objeto em C #. Usando o caso de teste abaixo ... funcionou para mim. Aqui " MenuInfo " é meu objeto de classe 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
fonte
0

Primeiro você precisa incluir uma 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
fonte