2012-01-05 19 views
17

Próbuję deserializować niektóre dane JSON do obiektów dla aplikacji. Do tej pory wszystko było w porządku, ponieważ właściwości danych JSON były statyczne (klucz z wartością). Teraz mam wynik, w którym klucz jest dynamicznym kawałkiem danych.Deserializowanie JSON przy użyciu JSon.NET z dynamicznymi danymi

Oto przykład JSON URL:

http://en.wikipedia.org/w/api.php?action=query&format=json&pageids=6695&prop=info

Powstały JSON na to:

{ "query" : { "pages" : { "6695" : { "counter" : "", 
      "lastrevid" : 468683764, 
      "length" : 8899, 
      "ns" : 0, 
      "pageid" : 6695, 
      "title" : "Citadel", 
      "touched" : "2012-01-03T19:16:16Z" 
     } } } } 

Okay, to świetnie, z wyjątkiem nie mogę deserializować "stron" danych do obiekt. Gdybym miał określić klasę dla stron musiałaby wyglądać następująco:

public class 6695 
{ 
    public string counter { get; set; } 
    public int lastrevid { get; set; } 
    public int length { get; set; } 
    public int ns { get; set; } 
    public int pageid { get; set; } 
    public string title { get; set; } 
    public string touched { get; set; } 
} 

W celu deserialze zawartość (używając JsonConvert.Deserialize (jsondata)) i wszyscy wiemy, że nie możemy mieć klasa o nazwie 6695. Nie tylko to, nazwa klasy musiałaby być inna (na przykład pageid = 7145 musiałaby być klasa 7145).

Mogę pozbyć się niektórych wartości, jeśli używam czegoś takiego jak JObject.Parse (zawartość), a następnie dostęp do elementów jako JArrays, ale jest to dość brzydkie i wciąż utknąłem na próbach wydobycia danych z tablicy stron .

Poszukuję kogoś, kto może w tym pomóc. Nie wydaje mi się, żeby było to rzadkie, to po prostu nie dane JSON, z którymi miałem do czynienia, i nie wiem, jak sobie z tym poradzić.

Dzięki!

PS zapomniałem wspomnieć, że jest to na Windows Phone 7, więc "dynamiczny" nie jest dostępny!

+0

Czy nie 6695, po prostu być nazwa właściwości, a nie nazwa klasy? Wciąż problem, ale może możesz wyszukać i zamienić właściwość liczbową na pewną stałą nazwę. Nie jestem pewien, w jaki sposób Json.NET radzi sobie z tym, ale może możesz spróbować deserializować go jako słownik określonego typu obiektu? –

+0

Prawdopodobnie trochę spóźniłem się na to przyjęcie, ale lib newtonsoft ma JObject dla tego ... var obj = JObject.Parse (jsonString); zasadniczo traktuje dane jak złożony zagnieżdżony słownik podobny do zachowań javascript w przeglądarce. Otrzymasz z powrotem instancję "JObject", która pozwala ci uzyskać dostęp do wszystkiego za pomocą składni tablic np .: var page = obj ["pages"] ["6695"] – War

Odpowiedz

18

Oto sposób korzystania z usługi https://github.com/facebook-csharp-sdk/simple-json (https://nuget.org/packages/SimpleJson).

var text = "{\"query\":{\"pages\":{\"6695\":{\"pageid\":6695,\"ns\":0,\"title\":\"Citadel\",\"touched\":\"2012-01-03T19:16:16Z\",\"lastrevid\":468683764,\"counter\":\"\",\"length\":8899}}}}"; 

(Korzystanie dynamiczny)

dynamic json = SimpleJson.DeserializeObject(text); 
string title = json.query.pages["6695"].title; 

foreach (KeyValuePair<string, dynamic> page in json.query.pages) 
{ 
    var id = page.Key; 
    var pageId = page.Value.pageid; 
    var ns = page.Value.ns; 
} 

(z użyciem silnie wpisane klasach)

class result 
{ 
    public query query { get; set; } 
} 
class query 
{ 
    public IDictionary<string, page> pages { get; set; } 
} 
class page 
{ 
    public long pageid { get; set; } 
    public string title { get; set; } 
} 

var result = SimpleJson.DeserializeObject<result>(text); 

[Update]

na Windows Phone, gdzie dynamiczny nie jest obsługiwany, a ci nie chcę używać silnie typowanych klas.

var json = (IDictionary<string, object>)SimpleJson.DeserializeObject(text); 
var query = (IDictionary<string, object>)json["query"]; 
var pages = (IDictionary<string, object>)query["pages"]; 
var pageKeys = pages.Keys; 
var page = (IDictionary<string, object>)pages["6695"]; 
var title = (string)page["title"]; 
+0

Świetnie! To działa (Json.NET jest taki sam i może używać silnie typowanych klas tak samo jak SimpleJson robi).) Dzięki. – Bil

+0

Po prostu wpadłem na ten problem, próbując przeanalizować szczegóły pliku GIST z GitHub.Dziękuję bardzo za odpowiedź tutaj.Nie myślałem, aby używać IDictionary! –

28

Najprostsza metoda. W tym konkretnym przypadku prawdopodobnie miałoby nastąpić dynamic.

dynamic data = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json); 
var lastRevId = data.query.pages["6695"].lastrevid; 

Można odwołać się do dowolnego elementu przez to [] nazwa więc można zrobić coś jak data["query"]["pages"]["6695"]["lastrevid"]. Otrzyma to wszystkie te małe obiekty, których nazwa nie jest poprawna w języku C#.

+2

Wygląda, jakby to było dla wp7, które nie obsługuje dynamicznego :(I Zostawię to tutaj dla każdego, kto nie jest ograniczony przez C# 3 – Buildstarted

+0

Nie musisz używać ogólnej metody **, możesz po prostu przejść do 'danych dynamicznych = JsonConvert.DeserializeObject (json);' –

0

Co powiesz na proste wyszukiwanie i zamiana w ciągu JSON? Choć może nie być to najbardziej eleganckie rozwiązanie, byłoby to najbardziej pragmatyczne.

+0

Taa, ktoś tylko wpadł na to na Twitterze, dając mu szansę, prawdopodobnie zadziała i nie jest zbyt obślizgły – Bil

0

Może po prostu użyć jednego atrybutu zastrzeżonego zawierać typ obiektu, a następnie użyć typu bazowego, jak pokazano w tym artykule: Dynamic types with JSON.NET

1

Korzystanie Json.NET można po prostu zrobić:

Dictionary<string,object> result = JsonConvert.DeserializeObject<Dictionary<string,object>>(json); 
foreach(var item in result) 
    Console.WriteLine(item.Key + " " + item.Value); 
1

Mam nadzieję, że poniższy przykład pomoże. Zawsze projektuję model pasujący do jsona. O wiele lepiej jest pracować z obiektem, gdy jest to twój własny projekt modelu.

Bardzo łatwo jest wygenerować model C# z json. I korzystać z tej strony, aby wygenerować model: http://json2csharp.com

Kompletny przykładem jest:

C# Kod:

var targetsObject = Newtonsoft.Json.JsonConvert.DeserializeObject<YourModel>(jsonString); 

JSON:

{ 
     "investors": [ 
     { 
      "name": "06", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "3.5" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "" 
      }, 
      { 
       "name": "VA", 
       "value": "5.5" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "6.0" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "" 
      } 
      ] 
     }, 
     { 
      "name": "07", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "3.5" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "7.0" 
      }, 
      { 
       "name": "VA", 
       "value": "5.5" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "" 
      } 
      ] 
     }, 
     { 
      "name": "08", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "3.5" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "7.0" 
      }, 
      { 
       "name": "VA", 
       "value": "5.5" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "" 
      } 
      ] 
     }, 
     { 
      "name": "09", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "3.5" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "" 
      }, 
      { 
       "name": "VA", 
       "value": "5.5" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "" 
      } 
      ] 
     }, 
     { 
      "name": "10", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "" 
      }, 
      { 
       "name": "VA", 
       "value": "" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "2.0" 
      } 
      ] 
     }, 
     { 
      "name": "11", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "3.5" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "" 
      }, 
      { 
       "name": "VA", 
       "value": "6.0" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "6.0" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "" 
      } 
      ] 
     }, 
     { 
      "name": "12", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "3.5" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "" 
      }, 
      { 
       "name": "VA", 
       "value": "5.5" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "6.0" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "" 
      } 
      ] 
     }, 
     { 
      "name": "13", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "" 
      }, 
      { 
       "name": "VA", 
       "value": "" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "2.0" 
      } 
      ] 
     } 
     ] 
    } 

Model:

public class Program 
    { 
     public string name { get; set; } 
     public string value { get; set; } 
    } 

    public class Investor 
    { 
     public string name { get; set; } 
     public List<Program> programs { get; set; } 
    } 

    public class RootObject 
    { 
     public List<Investor> investors { get; set; } 
    } 
Powiązane problemy