2013-04-18 3 views
5

정말이 문제를 2 일 동안 처리해야합니다. 어떻게 깊이 중첩 된 json 객체에서 데이터를 가져올 수 있습니까?깊게 중첩 된 json 객체에서 데이터 가져 오기

온라인 json 도구 http://www.jsoneditoronline.org/http://jsonformat.com/을 발견했습니다. json을 붙여 넣으면 모든 객체 배열이 표시되므로 데이터를 조사하고 원하는 정보를 얻을 수 있습니다.

foreach (JToken data in rates.ToArray()) 코드를 디버깅 할 때 다음 데이터를 볼 수 있습니다. 데이터를 가져올 수 없습니다. 오류가 발생한 경우에 따라 다릅니다. 마지막 오류는 다음과 같습니다. .

"@rateChange"값을 'Web.UI.Controllers.HomeController + RateInfo'유형으로 변환하는 중 오류가 발생했습니다.

System.String에서 Web.UI.Controllers.HomeController + RateInfo로 변환하거나 변환 할 수 없습니다.

이 문제에 대한 도움을 주시면 감사하겠습니다.

내 클래스

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

코드

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

===================== ========이 코드는 요약 배열에서 데이터를 가져옵니다. ============

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

하지만 최대한 빨리 데이터로 더 깊이 파고 시도로,이 대신하려고 내가

+0

디버거이보고있는 경우, 실제로 rates' '의 요소가 무엇인가. 즉, 시작 부분의 거대한 표현이 맞습니까? – millimoose

+0

안녕하세요 @millimoose 예 표현이 올바른지, json은 원격 서비스 – CareerChange

+0

에서 반환됩니다 무엇 입니까이 코드 라인은 무엇이 오류를 throw합니다. RateInfo rateInfo = JsonConvert.DeserializeObject (data.ToString()); – CareerChange

답변

9

을 필요로하는 데이터를 얻을 수 없습니다

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

편집 :

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

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

안녕 필, 죄송 합니다이 오류를 throw합니다. 키의 값이 무효 인 액세스 된 JObject 치. 0. 예상대로의 오브젝트 프로퍼티 명. – CareerChange

+0

@CareerChange 업데이트를 시도한 적이 있습니까? –

+0

안녕하세요 @ Phil 예, 이제 결과를 반환합니다, 대단히 감사합니다. 시간이 있다면, HotelSummary 배열을 반복하는 방법을 알려주고 모든 데이터를 가져올 수 있습니까? 반환 된 데이터는 여러 개의 HotelSummary 배열을가집니다. 당신이 할 수 없다면 문제 없어요,이 문제를 고치기 위해 다시 고마워요. – CareerChange

0

이 확장 방법을 재귀를 사용하여 깊게 중첩 된 json을 반복하고 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; 
    } 

사용 방법 :

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