2015-03-28 2 views
0

У меня есть следующие JSON данные из веб-сервиса:Проблема разбора JSON данных

{"zip_codes":[{"zip_code":"36451","distance":0,"city":"Grove Hill","state":"AL"}, {"zip_code":"36446","distance":8.031,"city":"Fulton","state":"AL"}]} 

Я использую Newtonsoft.Json библиотеки для .Net и пытается разобрать строку выше для городов. Я продолжаю получать ошибку.

public List<string> getZipCodesWithinRadius(string zipCode, string radius) 
     { 
      List<string> l = new List<string>(); 

      string apiKey = @"----"; 
      string apiFormat = @"radius.json"; 
      string baseUrl = @"http://www.zipcodeapi.com/rest/"; 

      string url = baseUrl + apiKey + @"/" + apiFormat + @"/" + zipCode + @"/" + radius + @"/mile"; 


      WebClient client = new WebClient(); 

      Stream stream = client.OpenRead(@"http://www.zipcodeapi.com/rest/uOrUEaRSt9KTqO0OuIFXxwH0uP7uX6AsU2mzcesGncAN1BCvjhtQNbRi0YNX4oqZ/radius.json/36451/10/mile"); 

      StreamReader rdr = new StreamReader(stream); 

      List<ZipCode> ll = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ZipCode>>(rdr.Read().ToString()); 


      foreach (ZipCode z in ll) 
      { 
       l.Add(z.city); 
      } 
      return l; 
     } 

Вызывает следующую ошибку:

Error converting value 123 to type 'System.Collections.Generic.List`1[Petrologic.Tools.ZipCode]'. Path '', line 1, position 3. 

Вот мой объект:

public class ZipCode 
    { 
     public ZipCode() { } 
     [JsonProperty(PropertyName="zip_code")] 
     public string zip_code { get; set; } 
     [JsonProperty(PropertyName = "distance")] 
     public double distance { get; set; } 
     [JsonProperty(PropertyName = "city")] 
     public string city { get; set; } 
     [JsonProperty(PropertyName = "state")] 
     public string state { get; set; } 
    } 

Пожалуйста, помогите

+1

'rdr.Read()' читает только один символ. Вероятно, вы хотите использовать 'ReadToEnd()'. Но это все равно не сработает, вам может понадобиться класс 'ZipCodes', который имеет свойство« Список ZipCode »и десериализуется в этот тип. И не публикуйте свой api-ключ публично. – Crowcoder

ответ

2

Во-первых, перейти к http://json2csharp.com/ и опубликовать JSON там, и получить назад следующие классы C#:

public class ZipCode 
{ 
    public string zip_code { get; set; } 
    public double distance { get; set; } 
    public string city { get; set; } 
    public string state { get; set; } 
} 

public class RootObject 
{ 
    public List<ZipCode> zip_codes { get; set; } 
} 

Далее, вместо того, чтобы передавать JSON в строку, а затем десериализовать строку, вы можете десериализовать из потока напрямую.

И наконец, обязательно оберните все одноразовые предметы в заявлении using.

Таким образом:

public List<string> getZipCodesWithinRadius(string zipCode, string radius) 
    { 
     List<string> zipCodes = new List<string>(); 

     string apiKey = @"---REMOVED FROM ANSWER---"; 
     string apiFormat = @"radius.json"; 
     string baseUrl = @"http://www.zipcodeapi.com/rest/"; 

     string url = baseUrl + apiKey + @"/" + apiFormat + @"/" + zipCode + @"/" + radius + @"/mile"; 

     using (var client = new WebClient()) 
     using (var stream = client.OpenRead(url)) 
     using (var streamReader = new StreamReader(stream)) 
     using (var jsonReader = new JsonTextReader(streamReader)) 
     { 
      var root = new JsonSerializer().Deserialize<RootObject>(jsonReader); 
      if (root != null) 
      { 
       foreach (ZipCode z in root.zip_codes) 
       { 
        zipCodes.Add(z.city); 
       } 
      } 
     } 
     return zipCodes; 
    } 

Кстати, вы на самом деле не передавая входные аргументы для вашей службы - URL используется жёстко. Это просто тестовый код? Кажется, так, потому что если я сделаю client.OpenRead(url), тогда все будет работать так, как ожидалось.

Также, кстати, не следует ли называть ваш метод getCitiesWithinRadius()? В конце концов, они возвращают города, а не почтовые индексы. Кроме того, для городов с более чем одним почтовым индексом он возвращает дублированные названия городов.

1

Вы получаете эту ошибку, так как ваш корневой объект не является списком/массивом. (Ваш корневой объект имеет свойство zip_codes который возвращает список почтовых индексов)

Вы можете получить список просто:

using(WebClient client = new WebClient()) 
{ 
    var json = client.DownloadString(url); 
    List<ZipCode> ll = JObject.Parse(json)["zip_codes"].ToObject<List<ZipCode>>(); 
} 
Смежные вопросы