JSON mit C # deserialisieren

206

Ich versuche, den Graph API- Aufruf eines Facebook-Freundes in eine Liste von Objekten zu deserialisieren . Das JSON-Objekt sieht folgendermaßen aus:

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

Es funktioniert nicht, weil das primitive Objekt ungültig ist. Wie kann ich das deserialisieren?

Peter Mortensen
quelle
3
Schreiben Sie einen benutzerdefinierten Deserializer speziell für solche
Json
2
oder Sie können eine verwenden Dictionary<string,string>, check out: stackoverflow.com/questions/7699972/…
Kakashi
9
Ihr Freund: json2csharp.com
Nawfal
4
In visuellen Studios (ab 2013 oder 2012 mit installierten Web-Tools) ist genau diese Funktionalität integriert: Bearbeiten> Spezial
einfügen

Antworten:

264

Sie müssen eine Struktur wie folgt erstellen:

public class Friends
{

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

public class FacebookFriend
{

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

Dann sollten Sie in der Lage sein:

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

Die Namen meiner Klassen sind nur ein Beispiel. Sie sollten Eigennamen verwenden.

Hinzufügen eines Beispieltests:

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

Produziert:

id: 518523721, name: ftyft
id: 527032438, name: ftyftyf
id: 527572047, name: ftgft
id: 531141884, name: ftftft
Ikarus
quelle
3
Ja, es ist das, was ich nicht tun möchte, ein neues Objekt zu erstellen, um die Kinder zu halten. Ich denke, ich werde den Json unter Vertrag nehmen und das primitive Objekt herausnehmen. Danke dir.
@ Kevin Holditch danke für die Korrektur. Ich habe ein wichtiges Stück verpasst :)
Ikarus
2
Was mir an diesem System.Web.Script.Serialization.JavaScriptSerializer () nicht gefällt, ist, dass Sie immer einen definierten Typ T benötigen. In Java gibt es diese org.java-Bibliothek (Paket), die alle anonym bleibt: "JSONObject [" param "]. JSONarray (5)" etc
Sport
2
Es ist wichtig zu beachten, dass die Setter für die ID- und Namenseigenschaften öffentlich bleiben müssen. Wenn sie auf privat oder geschützt eingestellt sind, wird die Deserialisierung fehlerfrei ausgeführt, aber alle Daten sind null.
Isaac Zais
2
@sports, Sie können dies in C # tun, indem Sie auf eine Dynamik deserialisieren. Die Leistung ist jedoch viel besser, wenn Sie auf einen bekannten Typ deserialisieren.
PRMan
50

Manchmal bevorzuge ich dynamische Objekte:

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);
}
Bishoy Hanna
quelle
Sobald Beispiel einer Instanz , wo dies sinnvoll war , als das Objekt , das ich versuche , in deserialisieren eine Eigenschaft enthalten , die eine Schnittstelle war
soupy1976
2
Eine Erklärung wäre angebracht.
Peter Mortensen
Warum würden Sie dies der akzeptierten Antwort von @Icarus vorziehen?
Questioning
@Questioning: Beim Deserialisieren in Klassen mit starken Typen werden alle Eigenschaften vernachlässigt, die nicht in Ihren Klassen enthalten sind, während beim Deserialisieren in dynamische Objekte nur dynamische .Net-Objekte zurückgegeben werden, die für alle in Zukunft neu erstellten Eigenschaften flexibel sind, ohne dass Ihre Klassen aktualisiert werden müssen. (wie gesagt, manchmal nicht Standard)
Bishoy Hanna
38

Eine gute Möglichkeit, diese Klassen automatisch für Sie zu generieren, besteht darin, Ihre JSON-Ausgabe zu kopieren und hier einzufügen:

http://json2csharp.com/

Es bietet Ihnen einen Ausgangspunkt, um Ihre Klassen für die Deserialisierung zu verbessern.

Jack Fairfield
quelle
28

Sehr einfach können wir JSON-Inhalte mit Hilfe von Dictionary und JavaScriptSerializer analysieren. Hier ist der Beispielcode, mit dem ich JSON-Inhalte aus einer Ashx-Datei analysiere.

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();
Thomas
quelle
3
Diese Lösung ist sehr nützlich, wenn Sie nicht die Zeit haben oder Datenverträge erstellen müssen. Vor allem, wenn Sie nur an wenigen Attributen interessiert sind, die tief in der JSON-Struktur vergraben sind. In dieser Situation können Sie eine Reihe von Anweisungen verwenden, um zu dem zu navigieren, was Sie benötigen. Hinweis: Der zu deserialisierende Typ kann auch einer der folgenden sein: Dictionary <Zeichenfolge, Objekt> oder ArrayList (wenn ein Knoten eine sich wiederholende Struktur hat).
Philippe Monnet
1
Ich erhalte eine Laufzeitausnahme: Es wurde kein parameterloser Konstruktor für den Typ 'System.String' in der Codezeile Deserialize definiert.
RSK
20

Newtonsoft.JSONist eine gute Lösung für diese Art von Situationen. Auch Newtonsof.JSONist schneller als andere, wie zum Beispiel JavaScriptSerializer, DataContractJsonSerializer.

In diesem Beispiel können Sie Folgendes tun:

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

Anschließend können Sie jsonData in umwandeln JArrayund mithilfe einer forSchleife Daten bei jeder Iteration abrufen .

Außerdem möchte ich etwas hinzufügen:

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

Die Arbeit mit dynamischen Objekten und die Verwendung von Newtonsoft Serialize ist eine gute Wahl.

OnurBulbul
quelle
15

Ich stimme Icarus zu (hätte kommentiert, wenn ich könnte), aber anstatt eine CustomObject- Klasse zu verwenden, würde ich ein Wörterbuch verwenden (falls Facebook etwas hinzufügt).

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

oder

private class MyFacebookClass
{
    public IList<IDictionary<string, object>> data { get; set; }
}
Stijn Bollen
quelle
3
Die Verwendung von Dynamic funktioniert in den neuen Versionen besser. public IList<IDictionary<string, dynmaic>> data { get; set; }
BJury
3

Serialisierung:

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

Response.Write(jsonData);

Deserialisierung: :

Deserialisieren eines dynamischen Objekts

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

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

Response.Write(res.Name);
Ravula Sandeep
quelle
3

Sie können diese Erweiterungen verwenden

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
quelle
1

Hier ist eine weitere Site, die Ihnen mit dem gesamten Code hilft, den Sie benötigen, solange Sie eine korrekt formatierte JSON-Zeichenfolge zur Verfügung haben:

https://app.quicktype.io/

Liknes
quelle
1

Wenn Sie .NET Core 3.0 verwenden, können Sie mit System.Text.Json (das jetzt integriert ist) JSON deserialisieren.

Der erste Schritt besteht darin, Klassen zum Modellieren des JSON zu erstellen. Es gibt viele Tools, die dabei helfen können, und einige der Antworten hier listen sie auf.

Einige Optionen sind http://json2csharp.com , http://app.quicktype.io oder Visual Studio (Menü BearbeitenSpezial einfügenJSON als Klassen einfügen ).

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

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

Dann können Sie deserialisieren mit:

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

Wenn Sie Einstellungen wie die camelCaseHandhabung hinzufügen müssen , übergeben Sie die Serializer-Einstellungen wie folgt an den Deserializer:

var options = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
var person = JsonSerializer.Deserialize<Response>(json, options);
haldo
quelle