C# 使用 Newtonsoft 解析 JSON
Posted
技术标签:
【中文标题】C# 使用 Newtonsoft 解析 JSON【英文标题】:C# Parsing JSON w/ Newtonsoft 【发布时间】:2016-06-16 06:04:40 【问题描述】:我对 c# 很陌生,所以如果这没有任何意义,我深表歉意!
使用 C# 控制台应用程序,我很难解析详细的 json 响应并将 json 值分配给变量。我以为我可以通过将 json 反序列化为字符串来完成所有工作,直到大约 200 次迭代(我将对超过一百万个地址进行地理编码),我收到一个空结果数组的响应,导致我的应用程序崩溃。现在我正在尝试使用 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]。您会在 json 响应中注意到,第二个结果实例的准确度得分较低。而且,当我不更改 lat/lng 值来隐藏我的个人地址时,这两个实例是不同的,第二个的准确度要低得多。
虽然我成功获取了上述县的值,但我无法获得“formatted_address”的响应,以及每次通过 foreach 循环重置的值。
在“字段”部分,有多个同名对象。比如……
JToken _county = property.Value.SelectToken("name");
如何选择我要查找的“名称”?学区、时区、国会选区等。
再次抱歉,我发了这么长的帖子。我整个星期都在研究这个问题,就在我以为我已经弄明白的时候,一个愚蠢的地址必须不返回任何结果并破坏一切!!我真的很感谢比我聪明得多的人的帮助......在家工作的缺点,没有其他大脑可供选择:)
【问题讨论】:
您的第一段代码很好,但您应该尝试使用JsonConvert.DeserializeObject<YourType>(string)
反序列化为一个类。这样,您可以静态访问这些值。您可以通过array != null && array.Length > 0
检查数组中是否至少有一项。希望这会有所帮助!
嗨蒂姆。这是来自 geocod.io 的 Mathias。我们的一位客户分享了他为反序列化响应而编写的这个示例。随时在这里查看:gist.github.com/btompkins/8722291
【参考方案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.
这是因为“结果”对象存在,但它是空的(长度为零)。
【讨论】:
以上是关于C# 使用 Newtonsoft 解析 JSON的主要内容,如果未能解决你的问题,请参考以下文章
如何用c#解析这个json(使用Newtonsoft.Json)?
C# unity (发布到安卓端中使用)解析json字符串—使用微软官方的包Newtonsoft.Json
C# unity (发布到安卓端中使用)解析json字符串—使用微软官方的包Newtonsoft.Json
C# unity (发布到安卓端中使用)解析json字符串—使用微软官方的包Newtonsoft.Json