C# Parsing JSON w/ Newtonsoft

本文关键字:Newtonsoft JSON Parsing | 更新日期: 2023-09-27 18:37:11

我对 c# 很陌生,所以如果这没有任何意义,我深表歉意!

使用 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#解析JSON对象数组)。

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 响应中注意到,第二个结果实例的准确性分数较低。当我不更改纬度/液化值来隐藏我的个人地址时,这两个实例是不同的,第二个实例的准确性要低得多。

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

  3. 在"字段"部分中,有多个具有相同名称的对象。例如。。

    JToken _county = 属性。Value.SelectToken("name");

如何选择我要查找的"名称"? 学区、时区、国会选区等。

再次,我很抱歉这么长的帖子。我整个星期都在研究这个问题,就在我认为我已经弄清楚的时候,一个愚蠢的地址必须返回没有结果并破坏一切!!我真的很感谢比我聪明得多的人的帮助......在家工作的缺点,没有其他大脑可以挑选:)

C# Parsing JSON w/ Newtonsoft

如果您查看破坏代码的数据:

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

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

而不是您正在执行的测试:

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

你应该做:

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

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