2013-04-18 10 views
5

Sono davvero bloccato su questo problema ora per 2 giorni, come posso ottenere i dati da un oggetto json profondamente annidato.Ottenere dati da un oggetto json profondamente annidato

Ho trovato uno strumento json online http://www.jsoneditoronline.org/http://jsonformat.com/ che quando si incolla il json in esso, mostra tutti gli array di oggetti ecc., Così posso scavare nei dati e ottenere le informazioni che voglio.

Quando il debug del codice e mettere un punto di interruzione su: foreach (JToken data in rates.ToArray()) posso vedere i dati che sto cercando, non riesco proprio a ottenere i dati fuori, dipende da ciò che cerco dipende l'errore che ottengo, ultimo errore era .

Errore che converte il valore "@rateChange" per digitare 'Web.UI.Controllers.HomeController + RateInfo'.

Impossibile eseguire il cast o la conversione da System.String a Web.UI.Controllers.HomeController + RateInfo.

Qualsiasi aiuto con questo è molto apprezzato.

La mia classe

public class RateInfo 
     { 
      public string RateChange { get; set; } 
      public string Promo { get; set; } 
      public string PriceBreakdown { get; set; } 
      public bool NonRefundable { get; set; } 
      public string RateType { get; set; } 
      public int CurrentAllotment { get; set; } 
      public int? PromoId { get; set; } 
      public string PromoDescription { get; set; } 
      public string PromoType { get; set; } 
     } 

codice

IList<JToken> rates = root["HotelListResponse"]["HotelList"]["HotelSummary"][0]["RoomRateDetailsList"]["RoomRateDetails"]["RateInfos"]["RateInfo"].Children().ToList(); 


         IList<RateInfo> info = new List<RateInfo>(); 
         foreach (JToken data in rates.ToArray()) 
         { 
          RateInfo rateInfo = JsonConvert.DeserializeObject<RateInfo>(data.ToString()); 
          info.Add(rateInfo); 
         } 

JSON

{ "HotelListResponse" : { "HotelList" : { "@activePropertyCount" : "168", 
      "@size" : "2", 
      "HotelSummary" : [ { "@order" : "0", 
       "@ubsScore" : "360017", 
       "RoomRateDetailsList" : { "RoomRateDetails" : { "RateInfos" : { "@size" : "1", 
          "RateInfo" : { "@priceBreakdown" : "true", 
           "@promo" : "true", 
           "@rateChange" : "true", 
           "ChargeableRateInfo" : { "@averageBaseRate" : "68.62333", 
            "@averageRate" : "68.62333", 
            "@commissionableUsdTotal" : "205.87", 
            "@currencyCode" : "USD", 
            "@grossProfitOffline" : "14.06", 
            "@grossProfitOnline" : "27.44", 
            "@maxNightlyRate" : "77.87", 
            "@nightlyRateTotal" : "205.87", 
            "@total" : "205.87", 
            "NightlyRatesPerRoom" : { "@size" : "3", 
             "NightlyRate" : [ { "@baseRate" : "77.87", 
               "@promo" : "false", 
               "@rate" : "77.87" 
              }, 
              { "@baseRate" : "64.0", 
               "@promo" : "false", 
               "@rate" : "64.0" 
              }, 
              { "@baseRate" : "64.0", 
               "@promo" : "false", 
               "@rate" : "64.0" 
              } 
              ] 
             } 
            }, 
           "RoomGroup" : { "Room" : { "numberOfAdults" : 2, 
             "numberOfChildren" : 0, 
             "rateKey" : "f82ab843-49ee-481a-b53a-71647592b183" 
             } }, 
           "currentAllotment" : 0, 
           "nonRefundable" : true, 
           "promoDescription" : "Advance Purchase Special - non-refundable", 
           "promoId" : 200827770, 
           "promoType" : "Standard", 
           "rateType" : "MerchantStandard" 
           } 
          }, 
         "ValueAdds" : { "@size" : "1", 
          "ValueAdd" : { "@id" : "2048", 
           "description" : "Free Wireless Internet" 
           } 
          }, 
         "expediaPropertyId" : 3084588, 
         "maxRoomOccupancy" : 3, 
         "minGuestAge" : 0, 
         "propertyAvailable" : true, 
         "propertyRestricted" : false, 
         "quotedRoomOccupancy" : 2, 
         "rateCode" : 200371945, 
         "roomDescription" : "Standard Room with King size bed", 
         "roomTypeCode" : 477014 
         } }, 
       "address1" : "Stone Cellar Road", 
       "address2" : "High Usworth Newcastle", 
       "airportCode" : " ", 
       "amenityMask" : 18063491, 
       "city" : "Washington", 
       "confidenceRating" : 90, 
       "countryCode" : "GB", 
       "deepLink" : "http://travel.ian.com/index.jsp?pageName=hotAvail&cid=55505&hotelID=340461&mode=2&numberOfRooms=1&room-0-adult-total=2&room-0-child-total=0&arrivalMonth=11&arrivalDay=12&departureMonth=11&departureDay=15&showInfo=true&locale=en_US&currencyCode=USD", 
       "highRate" : 77.870000000000005, 
       "hotelId" : 340461, 
       "hotelInDestination" : true, 
       "hotelRating" : 3, 
       "latitude" : 54.922739999999997, 
       "locationDescription" : "Near Washington Old Hall", 
       "longitude" : -1.5342899999999999, 
       "lowRate" : 64, 
       "name" : "Mercure Newcastle George Washington Hotel Golf and Spa", 
       "postalCode" : "NE37 1PH", 
       "propertyCategory" : 1, 
       "proximityDistance" : 1.4710813, 
       "proximityUnit" : "MI", 
       "rateCurrencyCode" : "USD", 
       "shortDescription" : "<p><b>Location. </b> <br />Mercure Newcastle George Washington Hotel Golf and Spa is a business-friendly hotel located in Washington, close to Washington Old Hall, Angel of the North, and WWT", 
       "supplierType" : "E", 
       "thumbNailUrl" : "/hotels/4000000/3090000/3084600/3084588/3084588_84_t.jpg", 
       "tripAdvisorRating" : 3.5, 
       "tripAdvisorRatingUrl" : "http://www.tripadvisor.com/img/cdsi/img2/ratings/traveler/3.5-12345-4.gif", 
       "tripAdvisorReviewCount" : 215 
       }, 
       { "@order" : "1", 
       "@ubsScore" : "258461", 
       "RoomRateDetailsList" : { "RoomRateDetails" : { "RateInfos" : { "@size" : "1", 
          "RateInfo" : { "@priceBreakdown" : "true", 
           "@promo" : "false", 
           "@rateChange" : "true", 
           "ChargeableRateInfo" : { "@averageBaseRate" : "54.83667", 
            "@averageRate" : "54.83667", 
            "@commissionableUsdTotal" : "164.51001", 
            "@currencyCode" : "USD", 
            "@grossProfitOffline" : "11.69", 
            "@grossProfitOnline" : "22.38", 
            "@maxNightlyRate" : "63.47", 
            "@nightlyRateTotal" : "164.51001", 
            "@total" : "164.51", 
            "NightlyRatesPerRoom" : { "@size" : "3", 
             "NightlyRate" : [ { "@baseRate" : "50.52", 
               "@promo" : "false", 
               "@rate" : "50.52" 
              }, 
              { "@baseRate" : "50.52", 
               "@promo" : "false", 
               "@rate" : "50.52" 
              }, 
              { "@baseRate" : "63.47", 
               "@promo" : "false", 
               "@rate" : "63.47" 
              } 
              ] 
             } 
            }, 
           "RoomGroup" : { "Room" : { "numberOfAdults" : 2, 
             "numberOfChildren" : 0, 
             "rateKey" : "f82ab843-49ee-481a-b53a-71647592b183" 
             } }, 
           "currentAllotment" : 0, 
           "nonRefundable" : true, 
           "rateType" : "MerchantStandard" 
           } 
          }, 
         "expediaPropertyId" : 901118, 
         "maxRoomOccupancy" : 2, 
         "minGuestAge" : 0, 
         "propertyAvailable" : true, 
         "propertyRestricted" : false, 
         "quotedRoomOccupancy" : 2, 
         "rateCode" : 200369466, 
         "roomDescription" : "Standard room with double bed - Book early & Save", 
         "roomTypeCode" : 162976 
         } }, 
       "address1" : "Emerson Road", 
       "address2" : "District 5", 
       "airportCode" : "NCL", 
       "amenityMask" : 1507328, 
       "city" : "Washington", 
       "confidenceRating" : 85, 
       "countryCode" : "GB", 
       "deepLink" : "http://travel.ian.com/index.jsp?pageName=hotAvail&cid=55505&hotelID=207631&mode=2&numberOfRooms=1&room-0-adult-total=2&room-0-child-total=0&arrivalMonth=11&arrivalDay=12&departureMonth=11&departureDay=15&showInfo=true&locale=en_US&currencyCode=USD", 
       "highRate" : 63.469999999999999, 
       "hotelId" : 207631, 
       "hotelInDestination" : true, 
       "hotelRating" : 2, 
       "latitude" : 54.895090000000003, 
       "locationDescription" : "Near Washington Old Hall", 
       "longitude" : -1.55661, 
       "lowRate" : 50.520000000000003, 
       "name" : "Campanile Washington Newcastle Upon Tyne", 
       "postalCode" : "NE37 1LB", 
       "propertyCategory" : 1, 
       "proximityDistance" : 1.2526573000000001, 
       "proximityUnit" : "MI", 
       "rateCurrencyCode" : "USD", 
       "shortDescription" : "<p><b>Location. </b> <br />Campanile Washington Newcastle Upon Tyne is located in Washington, close to Washington Old Hall, Angel of the North, and WWT Washington Wetland Centre. Additional area", 
       "supplierType" : "E", 
       "thumbNailUrl" : "/hotels/1000000/910000/901200/901118/901118_20_t.jpg", 
       "tripAdvisorRating" : 3.5, 
       "tripAdvisorRatingUrl" : "http://www.tripadvisor.com/img/cdsi/img2/ratings/traveler/3.5-12345-4.gif", 
       "tripAdvisorReviewCount" : 55 
       } 
      ] 
     }, 
     "cacheKey" : "4ef59f3e:13e1c495694:-6e28", 
     "cacheLocation" : "10.186.168.74:7301", 
     "cachedSupplierResponse" : { "@cachedTime" : "0", 
      "@candidatePreptime" : "100", 
      "@matchedCurrency" : "true", 
      "@matchedLocale" : "true", 
      "@otherOverheadTime" : "3", 
      "@supplierCacheTolerance" : "MED", 
      "@supplierRequestNum" : "118", 
      "@supplierResponseNum" : "2", 
      "@supplierResponseTime" : "468", 
      "@tpidUsed" : "5200" 
     }, 
     "customerSessionId" : "0ABAA84A-59F3-E913-E1C2-495694906E33", 
     "moreResultsAvailable" : true, 
     "numberOfRoomsRequested" : 1 
    } } 

===================== ======== Questo codice funziona recuperando i dati dall'array di riepilogo ============

public class Hotelsummary 
    { 
     public string Name     { get; set; } 
     public string Address1    { get; set; } 
     public string Address2    { get; set; } 
     public string City     { get; set; } 
     public string PostalCode   { get; set; } 
     public string CountryCode   { get; set; } 
     public string ThumbNailUrl   { get; set; } 
     public string ShortDescription  { get; set; } 
     public double HotelRating   { get; set; } 
     public double TripAdvisorRating  { get; set; } 
     public string RateCurrencyCode  { get; set; } 
    } 


public IEnumerable<Hotelsummary> GetHotelsForLocationSearch() 
     { 
      var hotelDetails = GetHotelsFromEan.GetListOfHotels(); 
      var root = JObject.Parse(hotelDetails.ToString()); 
      IList<JToken> hotels = root["HotelListResponse"]["HotelList"]["HotelSummary"].Children().ToList(); 
      IList<Hotelsummary> hotelsummaries = hotels.Select(result => JsonConvert 
                      .DeserializeObject<Hotelsummary>(
                       result.ToString())).ToList(); 
      return hotelsummaries; 
     } 

Ma non appena cerco di scavare più in profondità i dati, non posso ottenere i dati che ha bisogno

+0

Se stai guardando questo nel debugger, che cosa sono in realtà gli elementi di 'rates'. Cioè, l'enorme espressione all'inizio è corretta? – millimoose

+0

Ciao @ millimoose sì l'espressione è corretta, il json è ciò che viene restituito dal servizio remoto – CareerChange

+0

Questa riga di codice è ciò che genera l'errore. RateInfo rateInfo = JsonConvert.DeserializeObject (data.ToString()); – CareerChange

risposta

9

Prova questo, invece:

IList<JToken> rates = root["HotelListResponse"]["HotelList"]["HotelSummary"][0]["RoomRateDetailsList"]["RoomRateDetails"]["RateInfos"].Children().ToList(); 

EDIT:

var rateInfo = json["HotelListResponse"]["HotelList"]["HotelSummary"][0]["RoomRateDetailsList"]["RoomRateDetails"]["RateInfos"]["RateInfo"]; 

var result =JsonConvert.DeserializeObject<RateInfo>(rateInfo .ToString()); 
+0

Ciao Phil, scusa che lancia questo errore. Valori JObject acceduti con valore chiave non valido: 0. Nome proprietà oggetto previsto. – CareerChange

+0

@CareerChange hai provato l'aggiornamento? –

+0

Ciao @Phil sì, ora sta restituendo i risultati, grazie mille. Se hai tempo, potresti dirmi come farei a scorrere gli array di HotelSummary e ottenere tutti i dati, dato che i dati restituiti hanno matrici multiple HotelSummary. Nessun problema se non puoi, grazie ancora per aver risolto questo problema – CareerChange

0

Questo metodo di estensione usa la ricorsione per eseguire il looping di un json profondo annidato e trovare il valore per una jProperty.

 public static TType JsonValue<TType>(this JObject obj, string key) 
    { 
     object result = null; //default to null if nothing is found 

     foreach (var item in obj) 
     { 
      var token = item; 

      if (token.Key.Equals(key, StringComparison.InvariantCultureIgnoreCase)) 
      { 
       result = token.Value.ToObject<TType>(); //return the value found 
       break; 
      } 

      if (!obj[token.Key].Children().Any()) 
       continue; 

       var jt = obj[token.Key].ToString(); 

       if (!jt.StartsWith("[")) 
       { 
        result = JsonValue<TType>(JObject.Parse(jt), key); 
       } 
       else 
       { 
        obj[token.Key].Children().ToList().ForEach(x => 
        { 
         //only the first match will be returned 
         result = JsonValue<TType>(JObject.Parse(x.ToString()), key); 
        }); 
       } 

      if (result != null) 
       break; 

     } 

     return (TType)result; 
    } 

Come si usa:

var myValue = jsonObject.JsonValue<string>("propName"); 
    var numbValue = jsonObject.JsonValue<long?>("propName2") ?? 0;