Como posso analisar JSON com c #?

455

Eu tenho o seguinte código:

var user = (Dictionary<string, object>)serializer.DeserializeObject(responsecontent);

A entrada responsecontenté JSON, mas não é analisada corretamente em um objeto. Como devo desserializar adequadamente?

Ola Ström
fonte
7
Ei, você pode querer tentar este link techblog.procurios.nl/k/n618/news/view/14605/14863/...
Vamsi
34
Jsonem System.Web.Helpers, há JsonQueryStringConverterno System.ServiceModel.Web, há JavascriptSerializerno System.Web.Script.Serialization, DataContractJsonSerializerno System.Runtime.Serialization.Json, Parreira MS tem ainda decidiu incluir terceiros Json.NETem sua API ASP.NET Web. Se você achou que isso não era suficiente, a MS está chegando, System.Jsonmas atualmente é imprópria para consumo. Caminho a percorrer Microsoft caminho a percorrer .... Escolho pelo namespace mais bonito.
Nawfal
4
@fusi o resto está em montagens separadas. Pesquise no Google o nome do espaço de nome / classe, você encontrará o assembly em que estão na documentação do msdn. Basta adicionar referência a essa montagem.
Nawfal
1
Só para completar, há também JsonValueno Windows.Data.Jsonque é apenas para Windows 8 e acima. Estou amando isso. MS está em uma missão :)
Nawfal
5
A NewtonSoft possui uma página de comparação em seu site (pode ser tendenciosa, mas ainda interessante): newtonsoft.com/json/help/html/jsonnetvsdotnetserializers.htm . Eu gostei especialmente a serialização dicionário Nonsensical linha :)
Ohad Schneider

Respostas:

365

Estou assumindo que você não está usando o Json.NET (pacote NuGet Newtonsoft.Json). Se esse for o caso, você deve tentar.

Possui os seguintes recursos:

  1. LINQ para JSON
  2. O JsonSerializer para converter rapidamente seus objetos .NET em JSON e vice-versa
  3. O Json.NET pode opcionalmente produzir JSON bem formatado e recuado para depuração ou exibição
  4. Atributos como JsonIgnore e JsonProperty podem ser adicionados a uma classe para personalizar como uma classe é serializada.
  5. Capacidade de converter JSON para e de XML
  6. Suporta várias plataformas: .NET, Silverlight e o Compact Framework

Veja o exemplo abaixo. Neste exemplo, a JsonConvertclasse é usada para converter um objeto de e para JSON. Possui dois métodos estáticos para esse fim. Eles são SerializeObject(Object obj)e DeserializeObject<T>(String json):

Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string json = JsonConvert.SerializeObject(product);
//{
//  "Name": "Apple",
//  "Expiry": "2008-12-28T00:00:00",
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}

Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);
MD Sayem Ahmed
fonte
18
Posso desserializar para uma varvariável de tipo, caso não conheça a estrutura completa do meu objetivo? Especificamente, estou consumindo as histórias de usuário do Rally e quero convertê-las em objetos.
Pedro Dusso
16
@VANDERWEYENJonathan - em um navegador da web moderno, JSON.parse (string) e JSON.stringify (object) manipulam datas como strings ISO8601, que é o formato descrito na resposta acima. Você pode atualizar seu padrão antes que as pessoas decidam que é irrelevante. As pessoas precisam de datas muito mais do que precisam do seu padrão.
precisa
3
@ PeterWone: Não, JSON.parse('{"Expiry": "2008-12-28T00:00:00"}').Expiryretorna a string "2008-12-28T00:00:00" , não uma data. pode ser transformado em uma Datevia new Date(str), mas JSON.parsenão sabe nada sobre datas. Você teria que passar um reviver que verificava cada valor de uma string em relação a um padrão.
TJ Crowder
3
Como 3,703 segundos são iguais a 3s e 703ms e o separador é um ponto decimal, eu digo a você que são segundos e três casas decimais.
27516 Peter Wone
38
Por que todo mundo tem esse problema com incluindo relevantes require, include, importou usingdeclarações em suas respostas. Essa linha machucaria?
Tomáš Zato - Restabelecer Monica
285

Como foi respondido aqui - Deserialize JSON em objeto dinâmico C #?

É bem simples usando o Json.NET:

dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;

Ou usando Newtonsoft.Json.Linq:

dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;
Dmitry Pavlov
fonte
13
@MaxHodges, você está certo. Eu apenas usei "seqüências de caracteres mágicas" embutidas para demonstrar como analisar os valores de string JSON. Não queria que parecesse complexo com escapamentos de aspas duplas. No código real, geralmente temos seqüências JSON obtidas de algum lugar como variáveis ​​ou passadas como parâmetros.
Dmitry Pavlov
4
Sem o .net 4, você não tem uma palavra-chave 'dinâmica'. Você pode usar 'var stuff' para declaração e, em vez de 'stuff.Name' e 'stuff.Address.City', você tem 'stuff ["Name"]' e 'stuff ["Address"] ["City"]' respectivamente .
Fil
1
@Fil Isso fornece um valor do tipo objecte você não pode usar a indexação em um arquivo object.
18717 Alex
138

Aqui estão algumas opções sem usar bibliotecas de terceiros:

// For that you will need to add reference to System.Runtime.Serialization
var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }"), new System.Xml.XmlDictionaryReaderQuotas());

// For that you will need to add reference to System.Xml and System.Xml.Linq
var root = XElement.Load(jsonReader);
Console.WriteLine(root.XPathSelectElement("//Name").Value);
Console.WriteLine(root.XPathSelectElement("//Address/State").Value);

// For that you will need to add reference to System.Web.Helpers
dynamic json = System.Web.Helpers.Json.Decode(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");
Console.WriteLine(json.Name);
Console.WriteLine(json.Address.State);

Consulte o link para obter mais informações sobre System.Web.Helpers.Json .

Atualização : Atualmente, a maneira mais fácil de obter Web.Helpersé usar o pacote NuGet .


Se você não se importa com versões anteriores do Windows, pode usar as classes do Windows.Data.Jsonespaço para nome:

// minimum supported version: Win 8
JsonObject root = Windows.Data.Json.JsonValue.Parse(jsonString).GetObject();
Console.WriteLine(root["Name"].GetString());
Console.WriteLine(root["Address"].GetObject()["State"].GetString());
qqbenq
fonte
Por que não vejo System.Web.Helpers no meu site ASP.NET (4.5)? XElement, XPathSelectElement não são conhecidos pelo meu VisualStudio. Como educá-lo?
Budda
Bem, você precisa adicionar referências para as bibliotecas correspondentes (conforme escrito nos comentários acima), consulte este artigo para obter mais informações. Além disso, essa pergunta pode ser interessante.
Qqbenq
2
Eu usei o método Web.Helpers descrito aqui, mas ocorreu um problema que foi resolvido por este post: stackoverflow.com/questions/7066726/…
Alex
1
trabalhando com WPF.By usando o seguinte namespace usando System.Runtime.Serialization.Json; using System.Xml.XPath; using System.Xml.Linq;
Shahid Neermunda
3
O Json.Net não é mais um componente de terceiros. A Microsoft os usa nos dias de hoje. É o serilizador padrão na API da Web.
Liam
62

Se o .NET 4 estiver disponível, confira: http://visitmix.com/writings/the-rise-of-json (archive.org)

Aqui está um trecho desse site:

WebClient webClient = new WebClient();
dynamic result = JsonValue.Parse(webClient.DownloadString("https://api.foursquare.com/v2/users/self?oauth_token=XXXXXXX"));
Console.WriteLine(result.response.user.firstName);

Esse último Console.WriteLine é bem legal ...

ElonU Webdev
fonte
Desculpe, parece que as coisas mudaram desde que eu respondi inicialmente. Vou ter que dar uma olhada ao redor e ver qual biblioteca é a correta ...
ElonU Webdev 7/12/12
7
Ansioso para você encontrar esta biblioteca. Edit: é este: dynamicjson.codeplex.com ?
user989056
1
Eu não sei qual classe ElonU quis dizer aqui, mas há "JsonValue" no Windows.Data.Json (que é apenas para Windows 8 e superior - estranho) e também o mesmo "JsonValue" no System.Json que ainda está em pré-visualização e Só Deus sabe se isso acontecerá. MS me confunde quando se trata de Json.
Nawfal #
35

Outra solução nativa para isso, que não requer bibliotecas de terceiros, mas uma referência ao System.Web.Extensions é o JavaScriptSerializer. Este não é um recurso interno novo, mas muito desconhecido, desde o 3.5.

using System.Web.Script.Serialization;

..

JavaScriptSerializer serializer = new JavaScriptSerializer();
objectString = serializer.Serialize(new MyObject());

e volta

MyObject o = serializer.Deserialize<MyObject>(objectString)
fr34kyn01535
fonte
2
Isso é muito bom, mas precisa dos componentes da Web; infelizmente, não funciona no .NET 4.0 Client Profile, que é a última versão do .NET para Windows XP. A instalação completa do .NET é possível, mas muitas pessoas aderem apenas ao perfil do cliente. Por outro lado, System.Runtime.Serialization.Json.DataContractJsonSerializer é suprido mesmo no perfil do cliente.
Al Kepp
3
@ fr34kyn01535: O Windows XP possui a segunda maior participação de mercado na área de trabalho. É relevante.
DonkeyMaster
Quando usei o JavaScriptSerializer para desseriarizar o meu objeto, ele funcionou, mas desserializou minha data incorretamente. Deveria ter sido 19/04/2018 12:00, mas desserializado para 18/04/2018 20:00. NewtonSoft.Json.JsonConvert desserializou-o conforme o esperado.
19418 Rich
21

Você também pode dar uma olhada no DataContractJsonSerializer

Pieter Germishuys
fonte
1
este é melhor, uma vez que é compatível com .NET 3.5
Mahmoud Fayez
Também é bastante mais rápido que JavaScriptSerializer, #
David
16

System.Json trabalha agora ...

Instale o nuget https://www.nuget.org/packages/System.Json

PM> Install-Package System.Json -Version 4.5.0

Amostra :

// PM>Install-Package System.Json -Version 4.5.0

using System;
using System.Json;

namespace NetCoreTestConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Note that JSON keys are case sensitive, a is not same as A.

            // JSON Sample
            string jsonString = "{\"a\": 1,\"b\": \"string value\",\"c\":[{\"Value\": 1}, {\"Value\": 2,\"SubObject\":[{\"SubValue\":3}]}]}";

            // You can use the following line in a beautifier/JSON formatted for better view
            // {"a": 1,"b": "string value","c":[{"Value": 1}, {"Value": 2,"SubObject":[{"SubValue":3}]}]}

            /* Formatted jsonString for viewing purposes:
            {
               "a":1,
               "b":"string value",
               "c":[
                  {
                     "Value":1
                  },
                  {
                     "Value":2,
                     "SubObject":[
                        {
                           "SubValue":3
                        }
                     ]
                  }
               ]
            }
            */

            // Verify your JSON if you get any errors here
            JsonValue json = JsonValue.Parse(jsonString);

            // int test
            if (json.ContainsKey("a"))
            {
                int a = json["a"]; // type already set to int
                Console.WriteLine("json[\"a\"]" + " = " + a);
            }

            // string test
            if (json.ContainsKey("b"))
            {
                string b = json["b"];  // type already set to string
                Console.WriteLine("json[\"b\"]" + " = " + b);
            }

            // object array test
            if (json.ContainsKey("c") && json["c"].JsonType == JsonType.Array)
            {
                // foreach loop test
                foreach (JsonValue j in json["c"])
                {
                    Console.WriteLine("j[\"Value\"]" + " = " + j["Value"].ToString());
                }

                // multi level key test
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][0]["Value"].ToString());
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][1]["Value"].ToString());
                Console.WriteLine("json[\"c\"][1][\"SubObject\"][0][\"SubValue\"]" + " = " + json["c"][1]["SubObject"][0]["SubValue"].ToString());
            }

            Console.WriteLine();
            Console.Write("Press any key to exit.");
            Console.ReadKey();
        }
    }
}
Zunair
fonte
1
Tentando encontrar um exemplo de como usar corretamente o System.Json moderno me trouxe aqui, depois de inúmeros resultados para o Json.NET/Newtonsoft.Json/"Newtson.Json "e iterações mais antigas do System.Json, que foram obsoletas há muito tempo. Obrigado por isso.
monkey0506
1
Isso me ajudou de uma maneira enorme. Muito obrigado.
MAK
10

Use esta ferramenta para gerar uma classe baseada em seu json:

http://json2csharp.com/

E então use a classe para desserializar seu json. Exemplo:

public class Account
{
    public string Email { get; set; }
    public bool Active { get; set; }
    public DateTime CreatedDate { get; set; }
    public IList<string> Roles { get; set; }
}


string json = @"{
  'Email': '[email protected]',
  'Active': true,
  'CreatedDate': '2013-01-20T00:00:00Z',
  'Roles': [
    'User',
    'Admin'
  ]
}";

Account account = JsonConvert.DeserializeObject<Account>(json);

Console.WriteLine(account.Email);
// [email protected]

Referências: https://forums.asp.net/t/1992996.aspx?Nested+Json+Deserialization+to+C+object+and+using+that+object https://www.newtonsoft.com/json/help /html/DeserializeObject.htm

Bruno Pereira
fonte
9

Tente o seguinte código:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("URL");
JArray array = new JArray();
using (var twitpicResponse = (HttpWebResponse)request.GetResponse())
using (var reader = new StreamReader(twitpicResponse.GetResponseStream()))
{
    JavaScriptSerializer js = new JavaScriptSerializer();
    var objText = reader.ReadToEnd();

    JObject joResponse = JObject.Parse(objText);
    JObject result = (JObject)joResponse["result"];
    array = (JArray)result["Detail"];
    string statu = array[0]["dlrStat"].ToString();
}
Muhammad Awais
fonte
Obrigado, eu queria a parte ["result" + variable] porque queria usar variáveis ​​a serem usadas aqui, o que você não pode fazer facilmente com o JSON.NET.
PHPHuru
Esta linha está fazendo alguma coisa ... JavaScriptSerializer js = new JavaScriptSerializer (); Desde já, obrigado.
Chris Catignani
9

System.Text.Json

O .NET core 3.0 vem com System.Text.Jsonbuilt-in, o que significa que você pode desserializar / serializar JSON sem usar uma biblioteca de terceiros.

Para serializar suas classes em sequência JSON:

var json = JsonSerializer.Serialize(order);

Para desserializar o JSON em uma classe fortemente tipada:

var order = JsonSerializer.Deserialize<Order>(json);

Então, se você tem uma aula como abaixo:

public class Order
{
    public int Id { get; set; }
    public string OrderNumber { get; set; }
    public decimal Balance { get; set; }
    public DateTime Opened { get; set; }
}

var json = JsonSerializer.Serialize(order);
// creates JSON ==>
{
    "id": 123456,
    "orderNumber": "ABC-123-456",
    "balance": 9876.54,
    "opened": "2019-10-21T23:47:16.85",
};

var order = JsonSerializer.Deserialize<Order>(json);
// ==> creates the above class

Uma coisa a notar é que System.Text.Json não lida automaticamente com camelCasepropriedades JSON ao usar seu próprio código (no entanto, ao usar solicitações MVC / WebAPI e o fichário do modelo).

Para resolver isso, você precisa passar JsonSerializerOptionscomo um parâmetro.

JsonSerializerOptions options = new JsonSerializerOptions
{        
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,  // set camelCase       
    WriteIndented = true                                // write pretty json
};

// pass options to serializer
var json = JsonSerializer.Serialize(order, options);
// pass options to deserializer
var order = JsonSerializer.Deserialize<Order>(json, options);

System.Text.Json também está disponível para .Net Framework e .Net Standard como um pacote Nu-get System.Text.Json

haldo
fonte
1
E se você não tiver uma aula? E se você souber vagamente o que os dados do json conterão? Ou se as chaves existem?
Cherona 15/04
@Cherona use JsonDocument.Parse.
haldo 15/04
5

A seguir, no site msdn , acho que ajuda a fornecer alguma funcionalidade nativa para o que você está procurando. Observe que ele está especificado para o Windows 8. Um exemplo desse site está listado abaixo.

JsonValue jsonValue = JsonValue.Parse("{\"Width\": 800, \"Height\": 600, \"Title\": \"View from 15th Floor\", \"IDs\": [116, 943, 234, 38793]}");
double width = jsonValue.GetObject().GetNamedNumber("Width");
double height = jsonValue.GetObject().GetNamedNumber("Height");
string title = jsonValue.GetObject().GetNamedString("Title");
JsonArray ids = jsonValue.GetObject().GetNamedArray("IDs");

Ele utiliza o espaço para nome Windows.Data.JSON .

TargetofGravity
fonte
6
Bom, mas "Cliente mínimo suportado: Windows 8"
watbywbarif
eu acho que é mais suportado e agora há newtonsoft json dll icouldnt encontrar windows.data.json
virtouso
3
@virtouso, como watbywbarif apontado é realmente bastante novo, o apoio no entanto mínima de Microsoft , só funciona no Windows 8.
TargetofGravity
4

Você pode usar as seguintes extensões

public static class JsonExtensions
{
    public static T ToObject<T>(this string jsonText)
    {
        return JsonConvert.DeserializeObject<T>(jsonText);
    }

    public static string ToJson<T>(this T obj)
    {
        return JsonConvert.SerializeObject(obj);
    } 
}
Hidayet R. Colkusu
fonte
0

Eu acho que a melhor resposta que eu já vi foi @MD_Sayem_Ahmed.

Sua pergunta é "Como posso analisar Json com C #", mas parece que você deseja decodificar Json. Se você deseja decodificá-lo, a resposta de Ahmed é boa.

Se você estiver tentando fazer isso no ASP.NET Web Api, a maneira mais fácil é criar um objeto de transferência de dados que retenha os dados que você deseja atribuir:

public class MyDto{
    public string Name{get; set;}
    public string Value{get; set;}
}

Você simplesmente adicionou o cabeçalho application / json à sua solicitação (se estiver usando o Fiddler, por exemplo). Você usaria isso na API da Web do ASP.NET da seguinte maneira:

//controller method -- assuming you want to post and return data
public MyDto Post([FromBody] MyDto myDto){
   MyDto someDto = myDto;
   /*ASP.NET automatically converts the data for you into this object 
    if you post a json object as follows:
{
    "Name": "SomeName",
      "Value": "SomeValue"
}
*/
   //do some stuff
}

Isso me ajudou muito quando eu estava trabalhando na minha API da Web e tornou minha vida super fácil.

cr1pto
fonte
0
         string json = @"{
            'Name': 'Wide Web',
            'Url': 'www.wideweb.com.br'}";

        JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
        dynamic j = jsonSerializer.Deserialize<dynamic>(json);
        string name = j["Name"].ToString();
        string url = j["Url"].ToString();
Fernando Meneses Gomes
fonte
-1
var result = controller.ActioName(objParams);
IDictionary<string, object> data = (IDictionary<string, object>)new System.Web.Routing.RouteValueDictionary(result.Data);
Assert.AreEqual("Table already exists.", data["Message"]);
Jidheesh Rajan
fonte
2
É melhor você explicar sua solução em vez de apenas postar alguma linha de código. Você pode ler Como escrevo uma boa resposta .
Massimiliano Kraus
Não se esqueça de incluir System.Webnas referências do seu projeto.
Ohad Cohen
-3
 using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(user)))
 {
    // Deserialization from JSON  
    DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(UserListing))
    DataContractJsonSerializer(typeof(UserListing));
    UserListing response = (UserListing)deserializer.ReadObject(ms);

 }

 public class UserListing
 {
    public List<UserList> users { get; set; }      
 }

 public class UserList
 {
    public string FirstName { get; set; }       
    public string LastName { get; set; } 
 }
Kobie Williams
fonte