Come posso analizzare JSON con C #?


455

Ho il codice seguente:

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

L'input responsecontentè JSON, ma non è analizzato correttamente in un oggetto. Come dovrei deserializzarlo correttamente?



34
C'è Jsonin System.Web.Helpers, c'è JsonQueryStringConverterin System.ServiceModel.Web, c'è JavascriptSerializerin System.Web.Script.Serialization, DataContractJsonSerializerin System.Runtime.Serialization.Json, diamine MS ha anche deciso di inserire terzi Json.NETnella sua API Web ASP.NET. Se pensavi che ciò non bastasse, la MS sta arrivando System.Jsonma al momento non è adatta al consumo. Modo di andare Microsoft modo di andare .... Scelgo dallo spazio dei nomi più bello.
nawfal,

4
@fusi gli altri sono in assemblee separate. Google il nome dello spazio dei nomi / classe, troverai l'assemblaggio che sono nella documentazione msdn. Basta aggiungere un riferimento a quell'assieme.
nawfal,

1
Giusto per completare, c'è anche JsonValuein Windows.Data.Jsoncui è solo per Windows 8 e versioni successive. Mi piace. MS è in missione :)
nawfal

5
NewtonSoft ha una pagina di confronto sul proprio sito (potrebbe essere distorta ma comunque interessante): newtonsoft.com/json/help/html/jsonnetvsdotnetserializers.htm . Mi è piaciuta soprattutto la riga di serializzazione del dizionario non sensuale :)
Ohad Schneider,

Risposte:


365

Presumo che tu non stia utilizzando Json.NET (pacchetto NuGet Newtonsoft.Json). In questo caso, dovresti provarlo.

Ha le seguenti caratteristiche:

  1. LINQ to JSON
  2. JsonSerializer per convertire rapidamente i tuoi oggetti .NET in JSON e viceversa
  3. Json.NET può facoltativamente produrre JSON ben formattato e rientrato per il debug o la visualizzazione
  4. Attributi come JsonIgnore e JsonProperty possono essere aggiunti a una classe per personalizzare la modalità di serializzazione di una classe
  5. Possibilità di convertire JSON in e da XML
  6. Supporta più piattaforme: .NET, Silverlight e Compact Framework

Guarda l' esempio sotto. In questo esempio, la JsonConvertclasse viene utilizzata per convertire un oggetto in e da JSON. Ha due metodi statici per questo scopo. Sono 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);

18
Posso deserializzare su una varvariabile di tipo, nel caso in cui non conosca la struttura completa del mio obiettivo? In particolare, sto consumando Racconti utente Rally e voglio convertirli in oggetti.
Pedro Dusso,

16
@VANDERWEYENJonathan - in un moderno browser Web, JSON.parse (stringa) e JSON.stringify (oggetto) gestiscono entrambe le date come stringhe ISO8601, che è il formato rappresentato nella risposta sopra. Potresti voler aggiornare il tuo standard prima che le persone decidano che è irrilevante. Le persone hanno bisogno di date molto più di quanto abbiano bisogno del tuo standard.
Peter vinto il

3
@PeterWone: No, JSON.parse('{"Expiry": "2008-12-28T00:00:00"}').Expiryrestituisce la stringa "2008-12-28T00:00:00" , non una data. esso può essere trasformato in una Datevia new Date(str), ma JSON.parsenon sa nulla di date. Dovresti passare un reviver che controlla ogni singolo valore di stringa rispetto a un modello.
TJ Crowder,

3
Dato che 3.703 secondi è lo stesso di 3s e 703ms e il separatore è un punto decimale, ti ho detto che questo è secondi con tre posizioni decimali.
Peter Wone,

38
Perché tutti hanno tale problema con inclusi rilevanti require, include, importo usingdichiarazioni nelle loro risposte. Quella linea sarebbe ferita?
Tomáš Zato - Ripristina Monica il

285

Come è stato risposto qui - Deserializzare JSON in oggetto dinamico C #?

È abbastanza semplice usare 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;

O 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;

13
@MaxHodges, hai ragione. Ho appena usato "stringhe magiche" in linea per dimostrare come analizzare i valori delle stringhe JSON. Non volevo che fosse complesso con le doppie virgolette di escape. Nel codice reale di solito abbiamo stringhe JSON ottenute da qualche parte come variabili o passate come parametri.
Dmitry Pavlov,

4
Senza .net 4 non hai una parola chiave "dinamica". Puoi usare 'var stuff' per la dichiarazione e invece di 'stuff.Name' e 'stuff.Address.City' hai rispettivamente 'stuff ["Nome"] "e" stuff ["Indirizzo"] ["Città"] " .
Fil

1
@Fil Questo ti dà un valore di tipo objecte non puoi usare l'indicizzazione su a object.
Alex,

138

Ecco alcune opzioni senza utilizzare librerie di terze parti:

// 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);

Vedere il collegamento per ulteriori informazioni su System.Web.Helpers.Json .

Aggiornamento : al giorno d'oggi il modo più semplice per ottenere Web.Helpersè utilizzare il pacchetto NuGet .


Se non ti interessano le versioni precedenti di Windows, puoi utilizzare le classi dello Windows.Data.Jsonspazio dei nomi:

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

Perché non vedo System.Web.Helpers nel mio sito Web ASP.NET (4.5)? XElement, XPathSelectElement non sono noti per VisualStudio. Come educarlo?
Budda,

Bene, devi aggiungere riferimenti per le librerie corrispondenti (come scritto nei commenti sopra), vedi questo articolo per maggiori informazioni. Inoltre, questa domanda potrebbe essere di interesse.
qqbenq,

2
Ho usato il metodo Web.Helpers qui descritto ma ho riscontrato un problema risolto da questo post: stackoverflow.com/questions/7066726/…
Alex

1
funziona con WPF.By usando il seguente spazio dei nomi usando System.Runtime.Serialization.Json; utilizzando System.Xml.XPath; utilizzando System.Xml.Linq;
Shahid Neermunda,

3
Json.Net non è quasi più un componente di terze parti. Microsoft lo usa da solo in questi giorni. È il serilizer predefinito sull'API Web.
Liam,

62

Se .NET 4 è disponibile per te, controlla: http://visitmix.com/writings/the-rise-of-json (archive.org)

Ecco uno snippet da quel sito:

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

L'ultima Console.WriteLine è piuttosto dolce ...


Mi dispiace, sembra che le cose siano cambiate da quando ho risposto inizialmente. Dovrò dare un'occhiata in giro e vedere quale libreria è quella corretta ...
ElonU Webdev

7
Non vedo l'ora di trovare questa biblioteca. Modifica: è questo: dynamicjson.codeplex.com ?
user989056

1
Non so cosa significasse la classe ElonU qui, ma c'è "JsonValue" in Windows.Data.Json (che è solo per Windows 8 e versioni successive - strano) e anche lo stesso "JsonValue" in System.Json che è ancora in anteprima e Solo Dio sa se uscirà mai. MS mi confonde quando si tratta di Json.
nawfal,

35

Un'altra soluzione nativa a questo, che non richiede librerie di terze parti ma un riferimento a System.Web.Extensions è JavaScriptSerializer. Questa non è una funzionalità incorporata nuova ma molto sconosciuta dal 3.5.

using System.Web.Script.Serialization;

..

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

e ritorno

MyObject o = serializer.Deserialize<MyObject>(objectString)

2
Questo è molto bello, ma ha bisogno dei componenti Web, quindi sfortunatamente non funziona nel profilo client .NET 4.0, che è l'ultima versione .NET per Windows XP. L'installazione completa di .NET è possibile, ma molte persone restano fedeli solo al profilo client. Al contrario, System.Runtime.Serialization.Json.DataContractJsonSerializer è supportato anche nel profilo client.
Al Kepp,

3
@ fr34kyn01535: Windows XP ha il secondo maggior market share sul desktop. È rilevante.
DonkeyMaster,

Quando ho usato JavaScriptSerializer per deseriarizzare il mio oggetto, ha funzionato ma ha deserializzato la mia data in modo errato. Avrebbe dovuto essere il 19/04/2018 alle 12:00 ma deserializzato il 18/04/2018 alle 08:00. NewtonSoft.Json.JsonConvert lo ha deserializzato come previsto.
Ricco


16

System.Json funziona ora ...

Installa nuget https://www.nuget.org/packages/System.Json

PM> Install-Package System.Json -Version 4.5.0

Campione :

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

1
Cercare di trovare un esempio di come utilizzare correttamente il moderno System.Json mi ha portato qui, dopo innumerevoli risultati per Json.NET/Newtonsoft.Json/"Newtson.Json "e precedenti versioni di System.Json da tempo deprecate. Grazie per questo.
monkey0506,

1
Questo mi ha aiutato moltissimo. Grazie mille.
FAI il

10

Usa questo strumento per generare una classe basata sul tuo json:

http://json2csharp.com/

E poi usa la classe per deserializzare il tuo json. Esempio:

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': 'james@example.com',
  'Active': true,
  'CreatedDate': '2013-01-20T00:00:00Z',
  'Roles': [
    'User',
    'Admin'
  ]
}";

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

Console.WriteLine(account.Email);
// james@example.com

Riferimenti: 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


9

Prova il seguente codice:

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

Grazie, volevo la parte ["risultato" + variabile] perché volevo usare le variabili da usare qui che non si possono fare facilmente con JSON.NET.
PHPGuru,

Questa linea sta facendo qualcosa ... JavaScriptSerializer js = new JavaScriptSerializer (); Grazie in anticipo.
Chris Catignani,

9

System.Text.Json

.NET core 3.0 include System.Text.Jsonbuilt-in, il che significa che puoi deserializzare / serializzare JSON senza usare una libreria di terze parti.

Per serializzare le tue classi su stringa JSON:

var json = JsonSerializer.Serialize(order);

Per deserializzare JSON in una classe fortemente tipizzata:

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

Quindi se hai una lezione come di seguito:

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

Una cosa da notare è che System.Text.Json non gestisce automaticamente le camelCaseproprietà JSON quando si utilizza il proprio codice (tuttavia, quando si utilizzano le richieste MVC / WebAPI e il raccoglitore di modelli).

Per risolvere questo problema, devi passare JsonSerializerOptionscome parametro.

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 è disponibile anche per .Net Framework e .Net Standard come pacchetto Nu-get System.Text.Json


1
E se non avessi una lezione? E se sapessi solo vagamente che cosa contengono i dati json? O se le chiavi esistono affatto?
Cherona,

@Cherona use JsonDocument.Parse.
haldo

5

Quanto segue dal sito msdn dovrei pensare che aiuti a fornire alcune funzionalità native per quello che stai cercando. Si noti che è specificato per Windows 8. Uno di questi esempi dal sito è elencato di seguito.

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");

Utilizza lo spazio dei nomi Windows.Data.JSON .


6
Bello, ma "Client supportato minimo: Windows 8"
watbywbarif

penso che non sia più supportato e ora c'è newtonsoft json dll che non riesce a trovare windows.data.json
virtouso

3
@virtouso, come ha sottolineato watbywbarif, è in realtà piuttosto nuovo, anche se il supporto minimo da parte di Microsoft , funziona solo con Windows 8.
TargetofGravity

4

È possibile utilizzare le seguenti estensioni

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

0

Penso che la migliore risposta che abbia mai visto sia stata @MD_Sayem_Ahmed.

La tua domanda è "Come posso analizzare Json con C #", ma sembra che tu voglia decodificare Json. Se vuoi decodificarlo, la risposta di Ahmed è buona.

Se si sta tentando di eseguire ciò in ASP.NET Web Api, il modo più semplice è creare un oggetto di trasferimento dati che contenga i dati che si desidera assegnare:

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

Devi semplicemente aggiungere l'intestazione application / json alla tua richiesta (se stai usando Fiddler, per esempio). Lo useresti quindi nell'API Web ASP.NET come segue:

//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
}

Questo mi ha aiutato molto quando lavoravo nella mia Web Api e mi ha reso la vita super facile.


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

-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"]);

2
Spieghi meglio la tua soluzione invece di pubblicare solo una riga di codice. Puoi leggere Come posso scrivere una buona risposta .
Massimiliano Kraus,

Non dimenticare di includere System.Webnei riferimenti del tuo progetto.
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; } 
 }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.