2016-03-03 61 views
0

我对c#非常陌生,所以我很抱歉如果这没有任何意义!C#解析JSON w/Newtonsoft

使用C#控制台应用程序,我很难分析详细的json响应并将json值分配给变量。我认为我已经通过将json反序列化为一个字符串来工作,直到大约200次迭代(我将对100多个地址进行地理编码),我收到了一个响应,其中有一个空的结果数组,导致应用程序崩溃。现在我正在尝试使用JObject,JProperty和JToken的新方法,但没有多少运气。

我的JSON例子是如下..

{ 
    "input": { 
    "address_components": { 
     "number": "123", 
     "predirectional": "E", 
     "street": "Main", 
     "suffix": "St", 
     "formatted_street": "E Main St", 
     "city": "Mesa", 
     "state": "AZ", 
     "zip": "85209", 
     "country": "US" 
    }, 
    "formatted_address": "123 E Main St, Mesa, AZ 85209" 
    }, 
    "results": [ 
    { 
     "address_components": { 
     "number": "123", 
     "predirectional": "E", 
     "street": "Main", 
     "suffix": "St", 
     "formatted_street": "E Main Ave", 
     "city": "Mesa", 
     "county": "Maricopa County", 
     "state": "AZ", 
     "zip": "85209", 
     "country": "US" 
     }, 
     "formatted_address": "123 E Main St, Mesa, AZ 85209", 
     "location": { 
     "lat": 33.123456, 
     "lng": -111.123456 
     }, 
     "accuracy": 1, 
     "accuracy_type": "range_interpolation", 
     "source": "TIGER\/Line\u00ae dataset from the US Census Bureau", 
     "fields": { 
     "congressional_district": { 
      "name": "Congressional District 5", 
      "district_number": 5, 
      "congress_number": "114th", 
      "congress_years": "2015-2017" 
     }, 
     "state_legislative_districts": { 
      "senate": { 
      "name": "State Senate District 16", 
      "district_number": "16" 
      }, 
      "house": { 
      "name": "State House District 16", 
      "district_number": "16" 
      } 
     }, 
     "school_districts": { 
      "unified": { 
      "name": "Gilbert Unified District", 
      "lea_code": "0403400", 
      "grade_low": "PK", 
      "grade_high": "12" 
      } 
     }, 
     "timezone": { 
      "name": "MST", 
      "utc_offset": -7, 
      "observes_dst": false 
     } 
     } 
    }, 
    { 
     "address_components": { 
     "number": "123", 
     "predirectional": "E", 
     "street": "Main", 
     "suffix": "St", 
     "formatted_street": "E Main St", 
     "city": "Mesa", 
     "county": "Maricopa County", 
     "state": "AZ", 
     "zip": "85209", 
     "country": "US" 
     }, 
     "formatted_address": "123 E Main St, Mesa, AZ 85209", 
     "location": { 
     "lat": 33.123456, 
     "lng": -111.123456 
     }, 
     "accuracy": 0.8, 
     "accuracy_type": "range_interpolation", 
     "source": "TIGER\/Line\u00ae dataset from the US Census Bureau", 
     "fields": { 
     "congressional_district": { 
      "name": "Congressional District 5", 
      "district_number": 5, 
      "congress_number": "114th", 
      "congress_years": "2015-2017" 
     }, 
     "state_legislative_districts": { 
      "senate": { 
      "name": "State Senate District 16", 
      "district_number": "16" 
      }, 
      "house": { 
      "name": "State House District 16", 
      "district_number": "16" 
      } 
     }, 
     "school_districts": { 
      "unified": { 
      "name": "Gilbert Unified District", 
      "lea_code": "0403400", 
      "grade_low": "PK", 
      "grade_high": "12" 
      } 
     }, 
     "timezone": { 
      "name": "MST", 
      "utc_offset": -7, 
      "observes_dst": false 
     } 
     } 
    } 
    ] 
} 

这打破了我原来的代码的JSON ..

{ 
    "input": { 
    "address_components": { 
     "number": "123", 
     "predirectional": "E", 
     "street": "Main", 
     "suffix": "St", 
     "formatted_street": "E Main St", 
     "city": "Mesa", 
     "state": "AZ", 
     "zip": "85209", 
     "country": "US" 
    }, 
    "formatted_address": "123 E Main St, Mesa, AZ 85209" 
    }, 
    "results": [] 
} 

原代码..

Uri uri = new Uri("https://api.geocod.io/v1/geocode?q=" + geocodioAddress + "&fields=cd,stateleg,school,timezone&api_key=" + app_key); 
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri); 
request.Method = WebRequestMethods.Http.Get; 
request.Accept = "application/json"; 

HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
StreamReader reader = new StreamReader(response.GetResponseStream()); 
string output = reader.ReadToEnd(); 
response.Close(); 

dynamic array = JsonConvert.DeserializeObject(output); 

if (array.results[0] != null) 
{ 
    // cont. 
} 

的错误味精是“索引超出范围,必须是非负数,小于集合的大小。”错误发生在“if(array.results [0]!= null)”。


现在,我敢肯定这是不是反正最好的办法,所以我想我会尝试一些新的东西(在这里找到:C# Parsing JSON array of objects)..

Uri uri = new Uri("https://api.geocod.io/v1/geocode?q=" + geocodioAddress + "&fields=cd,stateleg,school,timezone&api_key=" + app_key); 
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri); 
request.Method = WebRequestMethods.Http.Get; 
request.Accept = "application/json"; 

HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
StreamReader reader = new StreamReader(response.GetResponseStream()); 
string json = reader.ReadToEnd(); 
response.Close(); 

var resultObjects = AllChildren(JObject.Parse(json)) 
    .First(c => c.Type == JTokenType.Array && c.Path.Contains("results")) 
    .Children<JObject>(); 

foreach (JObject result in resultObjects) 
{ 
    foreach (JProperty property in result.Properties()) 
    { 
     JToken _county = property.Value.SelectToken("county"); 
     string county = Convert.ToString(_county); 

     // cont. 
    } 
} 

这看起来真的有希望,除了三件事..

  1. 我不想解析结果[1]。在json响应中您会注意到,第二个结果实例的准确性分数较低。当我不改变lat/lng值来隐藏我的个人地址时,这两个实例是不同的,第二个实例的准确性较差。

  2. 虽然我成功获得了上述县的值,但我无法获得“formatted_address”的响应,以及每次通过foreach循环重置该值。

  3. 在“fields”部分中,有多个具有相同名称的对象。例如..

    JToken _county = property.Value.SelectToken(“name”);

如何选择我要找的哪个“名称”?学区,时区,国会区等。

再次,我很抱歉这么长的帖子。我一整周都在努力研究这个问题,就在我认为自己已经想通了的时候,一个愚蠢的地址不得不返回任何结果并破坏一切!我很欣赏的人比我聪明很多的帮助...在家工作的缺点,没有其他心思挑:)

+0

你的第一个代码是好的,但你应该尝试使用'JsonConvert.DeserializeObject (string)'来反序列化一个类。这样,您可以静态访问这些值。你可以通过'array!= null && array.Length> 0'来检查数组中是否至少有一个项目。希望这可以帮助! –

+0

你好。这是来自geocod.io的Mathias。我们的一位客户分享了他编写的用于反序列化响应的例子。随时检查它在这里:https://gist.github.com/btompkins/8722291 – CodeMonkey

回答

1

如果你看一下,打破你的代码中的数据:

{ 
{ 
    "input": { 
    .. 
    }, 
    "formatted_address": "123 E Main St, Mesa, AZ 85209" 
    }, 
"results": [] 
} 

您将results定义为空数组。换句话说,它包含零个元素。因此,尝试访问此数组中的第一个元素(在索引0处)会导致出现错误。

相反,你正在做的测试:

if (array.results[0] != null) 
{ 
    // cont. 
} 

你应该做的:

if (array.Length != 0) 
{ 
    // cont. 
} 

,这是因为“结果”对象存在,但它是空(长度为零) 。