我们有一个用于处理第三方服务的网络服务。其中一个是SmartyStreets,用于验证美国地址。这是我的问题:随机,有一个JSON解析错误。重新提交地址似乎工作正常。我找不到表明问题的具体事情。以下是网址:
https://us-street.api.smartystreets.com/street-address?auth-id=xxxxx&auth-token=xxxxx&street=4952+W+STRONG+ST++CHICAGO+IL+60630-2420&candidates=10
没什么特别的,对吧?
以下是回复:
{"input_index":0,"candidate_index":0,"delivery_line_1":"4952 W Strong St","last_line":"Chicago IL 60630-2420","delivery_point_barcode":"606302420520","components":{"primary_number":"4952","street_predirection":"W","street_name":"Strong","street_suffix":"St","city_name":"Chicago","state_abbreviation":"IL","zipcode":"60630","plus4_code":"2420","delivery_point":"52","delivery_point_check_digit":"0"},"metadata":{"record_type":"S","zip_type":"Standard","county_fips":"17031","county_name":"Cook","carrier_route":"C021","congressional_district":"05","rdi":"Residential","elot_sequence":"0079","elot_sort":"A","latitude":41.97079,"longitude":-87.75191,"precision":"Zip9","time_zone":"Central","utc_offset":-6,"dst":true},"analysis":{"dpv_match_code":"Y","dpv_footnotes":"AABB","dpv_cmra":"N","dpv_vacant":"N","active":"Y"}}
该回复有错误(是的,我知道,没有[],我故意将它们拿出来)。以下是几秒钟后的相同回复:
{"input_index":0,"candidate_index":0,"delivery_line_1":"4952 W Strong St","last_line":"Chicago IL 60630-2420","delivery_point_barcode":"606302420520","components":{"primary_number":"4952","street_predirection":"W","street_name":"Strong","street_suffix":"St","city_name":"Chicago","state_abbreviation":"IL","zipcode":"60630","plus4_code":"2420","delivery_point":"52","delivery_point_check_digit":"0"},"metadata":{"record_type":"S","zip_type":"Standard","county_fips":"17031","county_name":"Cook","carrier_route":"C021","congressional_district":"05","rdi":"Residential","elot_sequence":"0079","elot_sort":"A","latitude":41.97079,"longitude":-87.75191,"precision":"Zip9","time_zone":"Central","utc_offset":-6,"dst":true},"analysis":{"dpv_match_code":"Y","dpv_footnotes":"AABB","dpv_cmra":"N","dpv_vacant":"N","active":"Y"}}
上面的回复没有错误并且工作正常。第一个错误如下:
-+Exception:
Newtonsoft.Json.JsonReaderException
-+Message:
Additional text encountered after finished reading JSON content: }. Path '', line 1, position 820.
-+Stack Trace:
at Newtonsoft.Json.JsonTextReader.Read()
at Newtonsoft.Json.Linq.JObject.Parse(String json, JsonLoadSettings settings)
at Newtonsoft.Json.Linq.JObject.Parse(String json)
at POS.Backend.Services.Providers.SmartyStreetsProvider.ValidateAddress_2622(String addressToValidate, EntityType entityType, Nullable`1 entityID, String entityName, Int32 storeID, Int32 tellerID) in C:\Users\Wayen\Documents\Projects\GIT\dPoint\Backend\Providers\SmartyStreetsProvider.cs:line 128
任何人都可以看到差异吗?我不能。我完全不知道为什么第一个有错误而第二个没有错误。
以下是发生错误的代码:
List<SmartyStreetsAPIResponseAddressResult> foundAddresses = new List<SmartyStreetsAPIResponseAddressResult>();
jsonResponse = jsonResponse.Replace("[", "").Replace("]", ""); //remove the extra [ ] at the start & end
string[] candidates = jsonResponse.Split(new string[] { "},{" }, StringSplitOptions.RemoveEmptyEntries);
foreach (string candidate in candidates)
{
//the split can remove parts of the JSON return value. Restore these parts
string correctedCandidateJSONValue = candidate;
if (correctedCandidateJSONValue.Substring(correctedCandidateJSONValue.Length - 2, 2) != "}\n" )
correctedCandidateJSONValue += "}";
if (correctedCandidateJSONValue.Substring(0, 1) != "{")
correctedCandidateJSONValue = correctedCandidateJSONValue.Insert(0, "{");
JObject addressData = JObject.Parse(correctedCandidateJSONValue);
JObject.Parse(correctedCandidateJSONValue)行发生错误。随机。顺便说一句,这只是在一周前开始的;近一年没有代码变更。
有时候JSON会带来一个额外的标签,例如“脚注”
{"input_index":0,"candidate_index":0,"delivery_line_1":"900 S Clark St","last_line":"Chicago IL 60605-3679","delivery_point_barcode":"606053679990","components":{"primary_number":"900","street_predirection":"S","street_name":"Clark","street_suffix":"St","city_name":"Chicago","state_abbreviation":"IL","zipcode":"60605","plus4_code":"3679","delivery_point":"99","delivery_point_check_digit":"0"},"metadata":{"record_type":"H","zip_type":"Standard","county_fips":"17031","county_name":"Cook","carrier_route":"C025","congressional_district":"07","building_default_indicator":"Y","rdi":"Residential","elot_sequence":"0454","elot_sort":"A","latitude":41.87051,"longitude":-87.63065,"precision":"Zip9","time_zone":"Central","utc_offset":-6,"dst":true},"analysis":{"dpv_match_code":"D","dpv_footnotes":"AAN1","dpv_cmra":"N","dpv_vacant":"N","active":"Y","footnotes":"H#"}}
由于dbc,它已得到修复。我的更新代码如下:
JsonSerializerSettings serializeSettings = new JsonSerializerSettings() { CheckAdditionalContent = false };
object deserializedJson = JsonConvert.DeserializeObject(jsonResponse, serializeSettings);
foreach (JObject candidate in (JArray)(deserializedJson))
{
//get only the address parts we need, which is the two lines (free-form) + the number, direction, name, suffix, city, state abbr, and zip code, along with PO BOX info if available
JToken lineOne = candidate.SelectToken("delivery_line_1");
JToken lineTwo = candidate.SelectToken("last_line");
JToken houseNumber = candidate.SelectToken("components.primary_number");
JToken directionToken = candidate.SelectToken("components.street_predirection");
JToken streetName = candidate.SelectToken("components.street_name");
JToken streetSuffix = candidate.SelectToken("components.street_suffix");
JToken city = candidate.SelectToken("components.city_name");
JToken state = candidate.SelectToken("components.state_abbreviation");
JToken zipCode = candidate.SelectToken("components.zipcode");
bool isPOBox = false;
if (lineOne.ToString().ToLower().Contains("po box"))
{
isPOBox = true;
}
JToken county = candidate.SelectToken("metadata.county_name");
foundAddresses.Add(new SmartyStreetsAPIResponseAddressResult((lineOne != null ? lineOne.ToString() : string.Empty),
(lineTwo != null ? lineTwo.ToString() : string.Empty),
(houseNumber != null ? houseNumber.ToString() : string.Empty),
(directionToken != null ? directionToken.ToString() : string.Empty),
(streetName != null ? streetName.ToString() : string.Empty),
(streetSuffix != null ? streetSuffix.ToString() : string.Empty),
(city != null ? city.ToString() : string.Empty),
(state != null ? state.ToString() : string.Empty),
(zipCode != null ? zipCode.ToString() : string.Empty),
(county != null ? county.ToString() : string.Empty),
isPOBox));
}
就像我在评论中所说,我是JSON的新手。我没有阅读它是如何工作的,而是看了一下从服务返回的字符串,并尝试自己解析它。我用括号将其拆分并迭代,而不是使用正确的设置反序列化它。更新的代码现在很好用。谢谢dbc!
答案 0 :(得分:0)
每个dbc,答案如下:
JsonSerializerSettings serializeSettings = new JsonSerializerSettings() { CheckAdditionalContent = false };
object deserializedJson = JsonConvert.DeserializeObject(jsonResponse, serializeSettings);
foreach (JObject candidate in (JArray)(deserializedJson))
{
//get only the address parts we need, which is the two lines (free-form) + the number, direction, name, suffix, city, state abbr, and zip code, along with PO BOX info if available
JToken lineOne = candidate.SelectToken("delivery_line_1");
JToken lineTwo = candidate.SelectToken("last_line");
JToken houseNumber = candidate.SelectToken("components.primary_number");
JToken directionToken = candidate.SelectToken("components.street_predirection");
JToken streetName = candidate.SelectToken("components.street_name");
JToken streetSuffix = candidate.SelectToken("components.street_suffix");
JToken city = candidate.SelectToken("components.city_name");
JToken state = candidate.SelectToken("components.state_abbreviation");
JToken zipCode = candidate.SelectToken("components.zipcode");
bool isPOBox = false;
if (lineOne.ToString().ToLower().Contains("po box"))
{
isPOBox = true;
}
JToken county = candidate.SelectToken("metadata.county_name");
foundAddresses.Add(new SmartyStreetsAPIResponseAddressResult((lineOne != null ? lineOne.ToString() : string.Empty),
(lineTwo != null ? lineTwo.ToString() : string.Empty),
(houseNumber != null ? houseNumber.ToString() : string.Empty),
(directionToken != null ? directionToken.ToString() : string.Empty),
(streetName != null ? streetName.ToString() : string.Empty),
(streetSuffix != null ? streetSuffix.ToString() : string.Empty),
(city != null ? city.ToString() : string.Empty),
(state != null ? state.ToString() : string.Empty),
(zipCode != null ? zipCode.ToString() : string.Empty),
(county != null ? county.ToString() : string.Empty),
isPOBox));
}