【问题标题】:Trying to consume SmartyStreets JSON with JSON.Net... "Cannot deserialize JSON array into type Components"尝试使用 JSON.Net 使用 SmartyStreets JSON...“无法将 JSON 数组反序列化为类型组件”
【发布时间】:2012-03-01 18:43:33
【问题描述】:

我正在尝试使用 SmartyStreets JSON LiveAddress API,但遇到了一些困难。我承认我对 JSON 不太熟悉。无论如何,我尝试了几种不同的方法,但通常会出现错误“无法将 JSON 数组反序列化为元数据类型”。

这是 JSON 字符串:

[{"input_index":0,"candidate_index":0,"delivery_line_1":"1600 Amphitheatre Pkwy","last_line":"Mountain View CA 94043-1351","delivery_point_barcode":"940431351000","components":{"primary_number":"1600","street_name":"Amphitheatre","street_suffix":"Pkwy","city_name":"Mountain View","state_abbreviation":"CA","zipcode":"94043","plus4_code":"1351","delivery_point":"00","delivery_point_check_digit":"0"},"metadata":{"record_type":"S","county_fips":"06085","county_name":"Santa Clara","carrier_route":"C058","congressional_district":"14"},"analysis":{"dpv_match_code":"Y","dpv_footnotes":"AABB","dpv_cmra":"N","dpv_vacant":"N","ews_match":false,"footnotes":"N#"}}]

我使用jsontocsharp webapp 来创建类。

这是我正在使用的代码:

using (var webClient = new WebClient())
        {
            var json = webClient.DownloadString("url");

            var md = JsonConvert.DeserializeObject<Metadata>(json);
            litTest.Text = md.county_name;
        }

然后抛出我上面提到的错误。

任何帮助将不胜感激。

谢谢你, 安德鲁

【问题讨论】:

    标签: c# asp.net json json.net smartystreets


    【解决方案1】:

    我是 SmartyStreets 的开发人员——感谢您使用我们的服务!

    您应该了解的主要内容是 JSON 响应是一组地址对象,而不仅仅是一个。这是因为地址可能不明确,需要消费者选择/确认。

    这意味着您需要告诉 Json.Net 将 JSON 反序列化为顶级地址对象,然后遍历每个地址以获取元数据(您试图直接解析元数据,这是行不通的,因为返回的数组中的每个地址都有一个元数据部分)。这基本上就是 L.B 在他的回答中所做的,只是为了使用动态,他增加了一些额外的开销。

    这是使用与您的问题相同的“DeserializeObject”的替代解决方案:

    namespace JsonFun
    {
        using System;
        using System.Net;
        using Newtonsoft.Json;
    
        class Program
        {
            private const string Url = "https://api.qualifiedaddress.com/street-address/?street=1600%20Amphitheatre%20Parkway&street2=&city=Mountain%20View&state=CA&zipcode=94043&candidates=10&auth-token=YOUR_AUTH_TOKEN_HERE";
    
            static void Main()
            {
                using (var webClient = new WebClient())
                {
                    var json = webClient.DownloadString(Url);
    
                    var candidate_addresses = JsonConvert.DeserializeObject<CandidateAddress[]>(json);
                    foreach (var item in candidate_addresses)
                        Console.WriteLine(item.metadata.county_name);
    
                    Console.ReadLine();
                }
            }
        }
    
        public class CandidateAddress
        {
            public int input_index { get; set; }
            public int candidate_index { get; set; }
            public string delivery_line_1 { get; set; }
            public string last_line { get; set; }
            public string delivery_point_barcode { get; set; }
            public Components components { get; set; }
            public Metadata metadata { get; set; }
            public Analysis analysis { get; set; }
        }
    
        public class Components
        {
            public string primary_number { get; set; }
            public string street_name { get; set; }
            public string street_suffix { get; set; }
            public string city_name { get; set; }
            public string state_abbreviation { get; set; }
            public string zipcode { get; set; }
            public string plus4_code { get; set; }
            public string delivery_point { get; set; }
            public string delivery_point_check_digit { get; set; }
        }
    
        public class Metadata
        {
            public string record_type { get; set; }
            public string county_fips { get; set; }
            public string county_name { get; set; }
            public string carrier_route { get; set; }
            public string congressional_district { get; set; }
            public double latitude { get; set; }
            public double longitude { get; set; }
            public string precision { get; set; }
        }
    
        public class Analysis
        {
            public string dpv_match_code { get; set; }
            public string dpv_footnotes { get; set; }
            public string dpv_cmra { get; set; }
            public string dpv_vacant { get; set; }
            public bool ews_match { get; set; }
            public string footnotes { get; set; }
        }
    }
    

    因此,最终将取决于您是要使用静态类型的响应对象还是动态响应对象。祝你好运!

    编辑:在示例响应中包含纬度/经度字段(新发布)。

    【讨论】:

    • 由于动态的解释问题,这似乎是更好的方法。我很欣赏这种洞察力。
    【解决方案2】:

    我更喜欢在这些情况下使用dynamic 对象(不需要创建丑陋的类)

    如:

    dynamic jsonObj = JsonUtils.JsonObject.GetDynamicJsonObject(json);
    foreach(var item in jsonObj)
    {
        Console.WriteLine(item.delivery_line_1 + ", " + 
                          item.last_line + ", " +
                          item.metadata.county_name + ", " +
                          item.components.street_name + ", " + 
                          item.components.city_name  );
    
    }
    

    这是Dynamic Json Object(只需复制并粘贴到您的项目)和some samples的来源

    PS:这是您的 json 字符串,格式更易读

    [
        {
            "input_index": 0,
            "candidate_index": 0,
            "delivery_line_1": "1600 Amphitheatre Pkwy",
            "last_line": "Mountain View CA 94043-1351",
            "delivery_point_barcode": "940431351000",
            "components": {
                "primary_number": "1600",
                "street_name": "Amphitheatre",
                "street_suffix": "Pkwy",
                "city_name": "Mountain View",
                "state_abbreviation": "CA",
                "zipcode": "94043",
                "plus4_code": "1351",
                "delivery_point": "00",
                "delivery_point_check_digit": "0"
            },
            "metadata": {
                "record_type": "S",
                "county_fips": "06085",
                "county_name": "Santa Clara",
                "carrier_route": "C058",
                "congressional_district": "14"
            },
            "analysis": {
                "dpv_match_code": "Y",
                "dpv_footnotes": "AABB",
                "dpv_cmra": "N",
                "dpv_vacant": "N",
                "ews_match": false,
                "footnotes": "N#"
            }
        }
    ]
    

    【讨论】:

    • 太棒了。我肯定需要更多地研究动态类。感谢您将我指向动态 Json 对象和示例……您真的帮了我大忙!
    • 是的,你用过什么工具吗?还是手工?
    • 这里有另一种方式:动态parsedJson = JsonConvert.DeserializeObject(rawResponse); Console.WriteLine(JsonConvert.SerializeObject(parsedJson, Formatting.Indented));
    • 小心使用动态,因为它会做一些解释。例如,我们的 house_number 值为“7041 1/2”。动态将其解释为我们甚至可以到达它之前的日期。结果是我们的字符串字段中的“1/2/7041 12:00:00 AM”。显然这是不对的。我们要么必须尝试重新解析该值,要么必须放弃动态。我们选择放弃动态模型并改用强类型模型,就像 @mdwhatcott 建议的那样。
    猜你喜欢
    • 2012-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 1970-01-01
    相关资源
    最近更新 更多