解析相同数据的JSON错误 - Newtonsoft.Json

时间:2017-08-19 02:01:56

标签: c# json

我们有一个用于处理第三方服务的网络服务。其中一个是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!

1 个答案:

答案 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));
            }