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 Modifica → Incolla speciale → Incolla 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.