Deserializza JSON con C #


206

Sto cercando di deserializzare la chiamata dell'API Graph di un amico di Facebook in un elenco di oggetti. L'oggetto JSON è simile a:

{"data":[{"id":"518523721","name":"ftyft"},
         {"id":"527032438","name":"ftyftyf"},
         {"id":"527572047","name":"ftgft"},
         {"id":"531141884","name":"ftftft"},
         {"id":"532652067","name"...

List<EFacebook> facebooks = new JavaScriptSerializer().Deserialize<List<EFacebook>>(result);

Non funziona perché l'oggetto primitivo non è valido. Come posso deserializzare questo?


3
scrivere un deserializzatore personalizzato appositamente per soddisfare tale json ...
Ashutosh Raina,

2
oppure puoi usare un Dictionary<string,string>, controlla: stackoverflow.com/questions/7699972/…
Kakashi,

9
Il tuo amico: json2csharp.com
nawfal,

4
In realtà gli studi visivi (a partire dal 2013 o 2012 con gli strumenti web installati) hanno questa esatta funzionalità integrata: Modifica> Incolla speciale> Incolla JSON come classi
floomby

Risposte:


264

Devi creare una struttura come questa:

public class Friends
{

    public List<FacebookFriend> data {get; set;}
}

public class FacebookFriend
{

    public string id {get; set;}
    public string name {get; set;}
}

Quindi dovresti essere in grado di fare:

Friends facebookFriends = new JavaScriptSerializer().Deserialize<Friends>(result);

I nomi delle mie lezioni sono solo un esempio. Dovresti usare nomi propri.

Aggiunta di un test di esempio:

string json =
    @"{""data"":[{""id"":""518523721"",""name"":""ftyft""}, {""id"":""527032438"",""name"":""ftyftyf""}, {""id"":""527572047"",""name"":""ftgft""}, {""id"":""531141884"",""name"":""ftftft""}]}";

Friends facebookFriends = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Friends>(json);

foreach(var item in facebookFriends.data)
{
    Console.WriteLine("id: {0}, name: {1}", item.id, item.name);
}

produce:

id: 518523721, name: ftyft
id: 527032438, name: ftyftyf
id: 527572047, name: ftgft
id: 531141884, name: ftftft

3
Sì, è quello che non voglio fare, creare un nuovo oggetto per contenere i bambini. Penso che porterò il json sottraendo l'oggetto primitivo. Grazie.

@Kevin Holditch grazie per la correzione. Mi sono perso un pezzo importante :)
Icaro

2
Quello che non mi piace di questo System.Web.Script.Serialization.JavaScriptSerializer () è che hai sempre bisogno di un tipo definito T. In Java c'è questa libreria org.java (pacchetto) che rimane tutto anonimo: "JSONObject [" param "]. JSONarray (5)" etc
sports

2
È importante notare che i setter per le proprietà id e name devono essere lasciati pubblici. Se sono impostati su privato o protetto, la deserializzazione verrà eseguita senza errori ma tutti i dati saranno nulli.
Isaac Zais,

2
@sports, puoi farlo in C # deserializzando su una dinamica, ma le prestazioni sono molto migliori se deserializzi su un tipo noto.
PRMan,

50

A volte preferisco oggetti dinamici:

public JsonResult GetJson()
{
  string res;
  WebClient client = new WebClient();

  // Download string
  string value = client.DownloadString("https://api.instagram.com/v1/users/000000000/media/recent/?client_id=clientId");

  // Write values
  res = value;
  dynamic dyn = JsonConvert.DeserializeObject(res);
  var lstInstagramObjects = new List<InstagramModel>();

  foreach(var obj in dyn.data)
  {
    lstInstagramObjects.Add(new InstagramModel()
    {
      Link = (obj.link != null) ? obj.link.ToString() : "",
      VideoUrl = (obj.videos != null) ? obj.videos.standard_resolution.url.ToString() : "",
      CommentsCount = int.Parse(obj.comments.count.ToString()),
      LikesCount = int.Parse(obj.likes.count.ToString()),
      CreatedTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds((double.Parse(obj.created_time.ToString()))),
      ImageUrl = (obj.images != null) ? obj.images.standard_resolution.url.ToString() : "",
      User = new InstagramModel.UserAccount()
             {
               username = obj.user.username,
               website = obj.user.website,
               profile_picture = obj.user.profile_picture,
               full_name = obj.user.full_name,
               bio = obj.user.bio,
               id = obj.user.id
             }
    });
  }

  return Json(lstInstagramObjects, JsonRequestBehavior.AllowGet);
}

Un esempio di un'istanza in cui ciò era utile era quando l'oggetto in cui stavo cercando di deserializzare conteneva una proprietà che era un'interfaccia
soupy1976,

2
Una spiegazione sarebbe in ordine.
Peter Mortensen,

Perché preferiresti questo rispetto alla risposta accettata da @Icarus?
Interrogazione del

@Domanda, la deserializzazione di classi di tipi forti trascurerebbe qualsiasi proprietà che non era nelle tue classi, mentre la deserializzazione di oggetti dinamici restituirebbe semplicemente l'oggetto dinamico .Net che è flessibile per qualsiasi nuova proprietà creata in futuro senza la necessità di aggiornare le tue classi. (come ho detto, a volte non standard)
Bishoy Hanna il

39

Un ottimo modo per generare automaticamente queste classi è copiare l'output JSON e inserirlo qui:

http://json2csharp.com/

Ti fornirà un punto di partenza per ritoccare le tue classi per la deserializzazione.


28

Molto facilmente possiamo analizzare il contenuto JSON con l'aiuto del dizionario e del JavaScriptSerializer. Ecco il codice di esempio con cui analizzo il contenuto JSON da un file ashx.

var jss = new JavaScriptSerializer();
string json = new StreamReader(context.Request.InputStream).ReadToEnd();
Dictionary<string, string> sData = jss.Deserialize<Dictionary<string, string>>(json);
string _Name = sData["Name"].ToString();
string _Subject = sData["Subject"].ToString();
string _Email = sData["Email"].ToString();
string _Details = sData["Details"].ToString();

3
Questa soluzione è molto utile se non si ha il tempo o se è necessario creare contratti di dati. Soprattutto se sei interessato solo a pochi attributi sepolti in profondità nella struttura JSON. In tale situazione è possibile utilizzare una serie di istruzioni per navigare verso ciò di cui hai bisogno. Nota: il tipo da deserializzare potrebbe anche essere uno dei seguenti: Dizionario <stringa, oggetto> o ArrayList (quando un nodo ha una struttura ripetuta).
Philippe Monnet,

1
Ottengo un'eccezione di runtime con questo: nessun costruttore senza parametri definito per il tipo di "System.String" sulla riga di codice Deserialize.
RSK,

20

Newtonsoft.JSONè una buona soluzione per questo tipo di situazioni. Inoltre Newtonsof.JSONè più veloce di altri, come JavaScriptSerializer,DataContractJsonSerializer .

In questo esempio, puoi:

var jsonData = JObject.Parse("your JSON data here");

Quindi puoi lanciare jsonData in JArraye puoi usare afor ciclo per ottenere dati ad ogni iterazione.

Inoltre, voglio aggiungere qualcosa:

for (int i = 0; (JArray)jsonData["data"].Count; i++)
{
    var data = jsonData[i - 1];
}

Lavorare con oggetti dinamici e usare la serializzazione di Newtonsoft è una buona scelta.


15

Sono d'accordo con Icarus (avrei commentato se potessi), ma invece di utilizzare una classe CustomObject , avrei usato un dizionario (nel caso Facebook aggiungesse qualcosa).

private class MyFacebookClass
{
    public IList<IDictionary<string, string>> data { get; set; }
}

o

private class MyFacebookClass
{
    public IList<IDictionary<string, object>> data { get; set; }
}

3
L'uso della dinamica funziona meglio nelle nuove versioni. public IList<IDictionary<string, dynmaic>> data { get; set; }
Giuria

3

serializzazione:

// Convert an object to JSON string format
string jsonData = JsonConvert.SerializeObject(obj);

Response.Write(jsonData);

Deserializzazione ::

Per deserializzare un oggetto dinamico

  string json = @"{
      'Name': 'name',
      'Description': 'des'
    }";

var res = JsonConvert.DeserializeObject< dynamic>(json);

Response.Write(res.Name);

3

Puoi usare queste 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);
   }
}


1

Se si utilizza .NET Core 3.0, è possibile utilizzare System.Text.Json (che è ora incorporato) per deserializzare JSON.

Il primo passo è creare classi per modellare JSON. Ci sono molti strumenti che possono aiutare in questo, e alcune delle risposte qui li elencano.

Alcune opzioni sono http://json2csharp.com , http://app.quicktype.io o utilizzano Visual Studio (menu ModificaIncolla specialeIncolla JSON come classi ).

public class Person
{
    public string Id { get; set; }
    public string Name { get; set; }
}

public class Response
{
    public List<Person> Data { get; set; }
}

Quindi puoi deserializzare usando:

var people = JsonSerializer.Deserialize<Response>(json);

Se è necessario aggiungere impostazioni, come la camelCasegestione, quindi passare le impostazioni del serializzatore nel deserializzatore in questo modo:

var options = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
var person = JsonSerializer.Deserialize<Response>(json, options);
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.