Deserializuj JSON za pomocą C #


206

Próbuję przekształcić wywołanie Graph API znajomego Facebooka na listę obiektów. Obiekt JSON wygląda następująco:

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

Nie działa, ponieważ pierwotny obiekt jest nieprawidłowy. Jak mogę to zrobić z postaci szeregowej?


3
napisz niestandardowy deserializator specjalnie dla takich
jsonów

2
lub możesz użyć Dictionary<string,string>, sprawdź: stackoverflow.com/questions/7699972/...
Kakashi,

9
Twój przyjaciel: json2csharp.com
nawfal

4
W rzeczywistości studia wizualne (z 2013 r. Lub 2012 r. Z zainstalowanymi narzędziami internetowymi) mają tę wbudowaną funkcję: Edycja> Wklej specjalnie> Wklej JSON As Classes
floomby

Odpowiedzi:


264

Musisz utworzyć taką strukturę:

public class Friends
{

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

public class FacebookFriend
{

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

Powinieneś być w stanie zrobić:

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

Nazwy moich klas są tylko przykładem. Powinieneś używać prawidłowych nazw.

Dodanie przykładowego testu:

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

Produkuje:

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

3
Tak, tego nie chcę robić, stwórz nowy obiekt do trzymania dzieci. Myślę, że podciągnę Jsona na wyjściu z prymitywnego obiektu. Dziękuję Ci.

@Kevin Holditch dzięki za korektę. Brakowało mi jednego ważnego kawałka :)
Icarus

2
W systemie System.Web.Script.Serialization.JavaScriptSerializer () nie podoba mi się to, że zawsze potrzebujesz określonego typu T. W Javie istnieje biblioteka (pakiet) org.java, która pozostaje anonimowa: „JSONObject [” param "]. JSONarray (5)" etc
sport

2
Należy zauważyć, że setery właściwości id i name muszą być publiczne. Jeśli są ustawione na prywatne lub chronione, deserializacja zostanie wykonana bez błędów, ale wszystkie dane będą zerowe.
Isaac Zais,

2
@sports, możesz to zrobić w C # przez deserializację do dynamiki, ale wydajność jest znacznie lepsza, jeśli deserializujesz do znanego typu.
PRMan

50

Czasami wolę obiekty dynamiczne:

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

Pewnym przykładem przykładu, w którym było to przydatne, było to, że obiekt, który próbowałem przekształcić do postaci szeregowej, zawierał właściwość będącą interfejsem
soupy1976

2
Wytłumaczenie byłoby w porządku.
Peter Mortensen,

Dlaczego wolisz to od zaakceptowanej odpowiedzi @Icarus?
Przesłuchanie

@ Pytanie, testowanie na klasy silnych typów pomijałoby wszelkie właściwości, które nie były w twoich klasach, podczas gdy deseriatyzowanie na obiektach dynamicznych po prostu zwracało dynamiczny obiekt .Net, który jest elastyczny dla każdej nowej właściwości utworzonej w przyszłości, bez konieczności aktualizowania klas. (jak powiedziałem, czasami niestandardowe)
Bishoy Hanna

39

Świetnym sposobem na automatyczne wygenerowanie tych klas jest skopiowanie danych wyjściowych JSON i wrzucenie ich tutaj:

http://json2csharp.com/

Zapewni to punkt wyjścia do poprawienia klas w celu deserializacji.


28

Bardzo łatwo możemy analizować zawartość JSON za pomocą słownika i JavaScriptSerializer. Oto przykładowy kod, za pomocą którego analizuję zawartość JSON z pliku 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
To rozwiązanie jest bardzo przydatne, jeśli nie masz czasu lub potrzeby tworzenia umów na dane. Zwłaszcza jeśli interesuje Cię tylko kilka atrybutów ukrytych głęboko w strukturze JSON. W takiej sytuacji możesz użyć szeregu instrukcji, aby przejść do tego, czego potrzebujesz. Uwaga: typ deserializacji może być także jednym z następujących: Słownik <ciąg, obiekt> lub ArrayList (gdy węzeł ma powtarzalną strukturę).
Philippe Monnet,

1
Otrzymuję wyjątek czasu wykonywania z tym: Nie zdefiniowano konstruktora bez parametrów dla typu „System.String” w wierszu kodu Deserialize.
RSK

20

Newtonsoft.JSONjest dobrym rozwiązaniem dla tego rodzaju sytuacji. Również Newtonsof.JSONjest szybsze niż w innych, takich jak JavaScriptSerializer, DataContractJsonSerializer.

W tym przykładzie możesz wykonać następujące czynności:

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

Następnie możesz rzutować jsonData na JArrayi możesz użyć forpętli, aby uzyskać dane przy każdej iteracji.

Chcę też coś dodać:

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

Praca z obiektem dynamicznym i używanie serializacji Newtonsoft to dobry wybór.


15

Zgadzam się z Icarusem (skomentowałbym, gdybym mógł), ale zamiast używać klasy CustomObject , użyłbym Słownika (na wypadek gdyby Facebook coś dodał).

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

lub

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

3
Korzystanie z dynamiki działa lepiej w nowych wersjach. public IList<IDictionary<string, dynmaic>> data { get; set; }
BJury

3

Serializacja:

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

Response.Write(jsonData);

Deserializacja ::

Aby deserializować obiekt dynamiczny

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

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

Response.Write(res.Name);

3

Możesz użyć tego rozszerzenia

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

Jeśli korzystasz z .NET Core 3.0, możesz użyć System.Text.Json (który jest teraz wbudowany) do deserializacji JSON.

Pierwszym krokiem jest utworzenie klas do modelowania JSON. Istnieje wiele narzędzi, które mogą w tym pomóc, a niektóre z odpowiedzi tutaj zawierają je.

Niektóre opcje to http://json2csharp.com , http://app.quicktype.io lub użyj Visual Studio (menu EdycjaWklej specjalnieWklej JSON jako klasy ).

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

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

Następnie możesz dokonać deserializacji za pomocą:

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

Jeśli musisz dodać ustawienia, takie jak camelCaseobsługa, a następnie przekaż ustawienia serializatora do deserializatora w następujący sposób:

var options = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
var person = JsonSerializer.Deserialize<Response>(json, options);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.