Newtonsoft.Json DeserializeObject只选择前两个元素

时间:2018-06-26 14:43:54

标签: c# .net json json.net json-deserialization

在C#类中,我试图反序列化从Google Place Autocomplete API(https://maps.googleapis.com/maps/api/place/autocomplete/output?parameters)获得的JSON字符串。

JSON如下:

{
   "predictions" : [
      {
         "description" : "11 Sukhumvit Road, Khlong Toei, Bangkok, Thailand",
         "id" : "ca5d46b0982d28ee26c0aa2e94785688cff38357",
         "matched_substrings" : [
            {
               "length" : 2,
               "offset" : 0
            },
            {
               "length" : 2,
               "offset" : 3
            }
         ],
         "place_id" : "ChIJa68zyuae4jAR11FuV_P2eh4",
         "reference" : "CoQBcwAAAMWiPU84BlqBn84vF-fg3RPvBxYUWuSVpQ9QQuQy7mVLU1Z68z-4GZyfXqS8NGiTZ0OcG4VdSUKYbA-7rOdIdeixd6i2i_fxzUg_pwui61Tm82zdYV22JLYKeuuBh77iQ36GII9AWhKQzFYIeMR3W1PvdiQihpjalJIT9u3tNhH9EhAqh48JGeGZDrLGDzHvPQPrGhTvSTqfGzX5H_j7XpP6RptgsWbyKA",
         "structured_formatting" : {
            "main_text" : "11 Sukhumvit Road",
            "main_text_matched_substrings" : [
               {
                  "length" : 2,
                  "offset" : 0
               },
               {
                  "length" : 2,
                  "offset" : 3
               }
            ],
            "secondary_text" : "Khlong Toei, Bangkok, Thailand"
         },
         "terms" : [
            {
               "offset" : 0,
               "value" : "11"
            },
            {
               "offset" : 3,
               "value" : "Sukhumvit Road"
            },
            {
               "offset" : 19,
               "value" : "Khlong Toei"
            },
            {
               "offset" : 32,
               "value" : "Bangkok"
            },
            {
               "offset" : 41,
               "value" : "Thailand"
            }
         ],
         "types" : [ "street_address", "geocode" ]
      },
      {
         "description" : "11 Sukhumvit Road, Khlong Toei Nuea, Watthana, Bangkok, Thailand",
         "id" : "14aa9ff6b7d97031a4722e3ea0bfb71db1f5e718",
         "matched_substrings" : [
            {
               "length" : 2,
               "offset" : 0
            },
            {
               "length" : 2,
               "offset" : 3
            }
         ],
         "place_id" : "ChIJ2Rp_B_2e4jAR5kGy-6xSlmM",
         "reference" : "CpQBgwAAAFKqcxX6_22KbMz8NrEelwf76VZ4FfrJDJhnIEsoi5Pvy6hAuq8rNri1Bcp4amObhNxOa20EMSc4F82mHCzh3d3XSI0C04ERlael6zn71QnwraPmML5VpUuVJT3_pd-SrSwzFtQ-ekJIHJ62Nr42JM2HUO06JVKRWCdn9ZTFItgHT7LsjsExS0riUj3HXIzKjxIQqBO8Iysg1LkSUw6qaUMEQhoUZFSQeIa8z_qeEF39Af0SLV_MWy0",
         "structured_formatting" : {
            "main_text" : "11 Sukhumvit Road",
            "main_text_matched_substrings" : [
               {
                  "length" : 2,
                  "offset" : 0
               },
               {
                  "length" : 2,
                  "offset" : 3
               }
            ],
            "secondary_text" : "Khlong Toei Nuea, Watthana, Bangkok, Thailand"
         },
         "terms" : [
            {
               "offset" : 0,
               "value" : "11"
            },
            {
               "offset" : 3,
               "value" : "Sukhumvit Road"
            },
            {
               "offset" : 19,
               "value" : "Khlong Toei Nuea"
            },
            {
               "offset" : 37,
               "value" : "Watthana"
            },
            {
               "offset" : 47,
               "value" : "Bangkok"
            },
            {
               "offset" : 56,
               "value" : "Thailand"
            }
         ],
         "types" : [ "street_address", "geocode" ]
      },
      {
         "description" : "11 Sukhumvit Alley, Khlong Tan Nuea, Watthana, Bangkok, Thailand",
         "id" : "232f132abc93383477f9c3db792a064ce52ca026",
         "matched_substrings" : [
            {
               "length" : 2,
               "offset" : 0
            },
            {
               "length" : 2,
               "offset" : 3
            }
         ],
         "place_id" : "ChIJPR10XTWe4jARztw9WrjPuA8",
         "reference" : "CpQBgwAAALdNIHByCxKkyKPlVQUGObR_b_iHimkMzCgWSvd_G87jwMsft34B4PKYtTMRsLDdMuw7G2bMma_hiHvazg8I63qDYoNCH_GLQn6e9VkHaHvvcGtXsnglkvP2LVDfK_CCzAhtB537S05y7k5_5hpquG4MhzATqAGUhSQ9QBHw8mfaG30WNuJNrptWlcr27gH3LRIQYZ5rX2MGoVb3lwkw40jm3BoU6JlknjT6CTGWBLQnIzgfyKQphi0",
         "structured_formatting" : {
            "main_text" : "11 Sukhumvit Alley",
            "main_text_matched_substrings" : [
               {
                  "length" : 2,
                  "offset" : 0
               },
               {
                  "length" : 2,
                  "offset" : 3
               }
            ],
            "secondary_text" : "Khlong Tan Nuea, Watthana, Bangkok, Thailand"
         },
         "terms" : [
            {
               "offset" : 0,
               "value" : "11"
            },
            {
               "offset" : 3,
               "value" : "Sukhumvit Alley"
            },
            {
               "offset" : 20,
               "value" : "Khlong Tan Nuea"
            },
            {
               "offset" : 37,
               "value" : "Watthana"
            },
            {
               "offset" : 47,
               "value" : "Bangkok"
            },
            {
               "offset" : 56,
               "value" : "Thailand"
            }
         ],
         "types" : [ "street_address", "geocode" ]
      },
      {
         "description" : "11, Netaji Subhash Marg, Dariya Ganj, New Delhi, Delhi, India",
         "id" : "55e3234dcff96c3dc1fee533d5b1a360c5e228a2",
         "matched_substrings" : [
            {
               "length" : 2,
               "offset" : 0
            },
            {
               "length" : 2,
               "offset" : 11
            }
         ],
         "place_id" : "ChIJPwQlCiD9DDkR2ermrNsq4m8",
         "reference" : "CoQBfwAAAIsyxBsZzJLM5JUm6H_r_imzC-7NgVxN8ZQCORVMTHE3crhQjBheH5Hq2jzpe1UitduWJYKoPG9hVD9diwx3daMPumSwHosJvA_0MzVtBLuo-f0SgS9wbBqBpWtLZ-oCy6AzQJac190_1wy3sI6mYlRdUVDEmQkzyW92sRWfqR8_EhBY7Cb8oiDXCUtm5QqfkIu9GhSznlDT1_7dklnqyGe1hSPgP37JOA",
         "structured_formatting" : {
            "main_text" : "11, Netaji Subhash Marg",
            "main_text_matched_substrings" : [
               {
                  "length" : 2,
                  "offset" : 0
               },
               {
                  "length" : 2,
                  "offset" : 11
               }
            ],
            "secondary_text" : "Dariya Ganj, New Delhi, Delhi, India"
         },
         "terms" : [
            {
               "offset" : 0,
               "value" : "11"
            },
            {
               "offset" : 4,
               "value" : "Netaji Subhash Marg"
            },
            {
               "offset" : 25,
               "value" : "Dariya Ganj"
            },
            {
               "offset" : 38,
               "value" : "New Delhi"
            },
            {
               "offset" : 49,
               "value" : "Delhi"
            },
            {
               "offset" : 56,
               "value" : "India"
            }
         ],
         "types" : [ "street_address", "geocode" ]
      },
      {
         "description" : "11 Charan Sanitwong Road, Bang Ao, Bang Phlat, Bangkok, Thailand",
         "id" : "2bdd14e344854148907b4dd5eeed92db76c780c8",
         "matched_substrings" : [
            {
               "length" : 2,
               "offset" : 0
            }
         ],
         "place_id" : "ChIJ6RiwusKb4jARnKT4ah2YlHo",
         "reference" : "CpQBgwAAABENThY5H5mVwiWidokHm3bz-z-rkRoch04vGIKZV6fhSEe4fs4EX2qYPfzJw7HMDjfItx7Dlz0lGtShu5Sot3WELkz4U8PdclUfrSpMcB1jYjVIfUlYGVBdrKP0k6T-XwLSt3VCOXYFVd4lOcEvq-5Dwfcy9RstwenOXXWHHueI3PH6H-wBYFSEmJKY2Sg7ghIQg14EpHqs9If1hO-Khv4tsxoU_a-1az6q5a1VnWAZtJPvZsS4sNc",
         "structured_formatting" : {
            "main_text" : "11 Charan Sanitwong Road",
            "main_text_matched_substrings" : [
               {
                  "length" : 2,
                  "offset" : 0
               }
            ],
            "secondary_text" : "Bang Ao, Bang Phlat, Bangkok, Thailand"
         },
         "terms" : [
            {
               "offset" : 0,
               "value" : "11"
            },
            {
               "offset" : 3,
               "value" : "Charan Sanitwong Road"
            },
            {
               "offset" : 26,
               "value" : "Bang Ao"
            },
            {
               "offset" : 35,
               "value" : "Bang Phlat"
            },
            {
               "offset" : 47,
               "value" : "Bangkok"
            },
            {
               "offset" : 56,
               "value" : "Thailand"
            }
         ],
         "types" : [ "street_address", "geocode" ]
      }
   ],
   "status" : "OK"
}

当我运行以下命令时:

using Newtonsoft.Json.Linq;
JObject jObj = (JObject)JsonConvert.DeserializeObject(content);
Debug.Write(jObj.Count);

jObj.Count的值为2,此时,如您在JSON文件中所看到的,它具有5个子元素。为什么会这样?

(我正在尝试为Google Maps场所创建WinForms自动完成文本框)

2 个答案:

答案 0 :(得分:4)

因为外部对象具有两个属性,即“预测”和“状态”。您正在查看外部对象中“预测”数组的元素。尝试以下方法:

JObject jObj = (JObject)JsonConvert.DeserializeObject(content);
JArray predictions = (JArray)jObj["predictions"];
Debug.Write(predictions.Count);    

提琴:https://dotnetfiddle.net/NdlwUI

答案 1 :(得分:1)

反序列化JSON的最完整方法是创建一个GooglePlaceModel类,该类包含JSON响应中的所有属性。

添加GooglePlaceModel后,您可以使用JsonConvert.DeserializeObject将JSON string转换为GooglePlaceModel

反序列化Json

public GooglePlaceModel DeserializeGooglePlaceJson(string json)
{
    return JsonConvert.DeserializeObject<GooglePlaceModel>(json);
} 

GooglePlaceModel

using System;
using System.Collections.Generic;
using System.Globalization;

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public class GooglePlaceModel
{
    [JsonProperty("predictions")]
    public List<Prediction> Predictions { get; set; }

    [JsonProperty("status")]
    public string Status { get; set; }
}

public class Prediction
{
    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("id")]
    public string Id { get; set; }

    [JsonProperty("matched_substrings")]
    public List<MatchedSubstring> MatchedSubstrings { get; set; }

    [JsonProperty("place_id")]
    public string PlaceId { get; set; }

    [JsonProperty("reference")]
    public string Reference { get; set; }

    [JsonProperty("structured_formatting")]
    public StructuredFormatting StructuredFormatting { get; set; }

    [JsonProperty("terms")]
    public List<Term> Terms { get; set; }

    [JsonProperty("types")]
    public List<TypeElement> Types { get; set; }
}

public class MatchedSubstring
{
    [JsonProperty("length")]
    public long Length { get; set; }

    [JsonProperty("offset")]
    public long Offset { get; set; }
}

public class StructuredFormatting
{
    [JsonProperty("main_text")]
    public string MainText { get; set; }

    [JsonProperty("main_text_matched_substrings")]
    public List<MatchedSubstring> MainTextMatchedSubstrings { get; set; }

    [JsonProperty("secondary_text")]
    public string SecondaryText { get; set; }
}

public class Term
{
    [JsonProperty("offset")]
    public long Offset { get; set; }

    [JsonProperty("value")]
    public string Value { get; set; }
}

public enum TypeElement { Geocode, StreetAddress };

internal static class Converter
{
    public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
        DateParseHandling = DateParseHandling.None,
        Converters = {
            TypeElementConverter.Singleton,
            new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
        },
    };
}

internal class TypeElementConverter : JsonConverter
{
    public override bool CanConvert(Type t) => t == typeof(TypeElement) || t == typeof(TypeElement?);

    public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null) return null;
        var value = serializer.Deserialize<string>(reader);
        switch (value)
        {
            case "geocode":
                return TypeElement.Geocode;
            case "street_address":
                return TypeElement.StreetAddress;
        }
        throw new Exception("Cannot unmarshal type TypeElement");
    }

    public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
    {
        if (untypedValue == null)
        {
            serializer.Serialize(writer, null);
            return;
        }
        var value = (TypeElement)untypedValue;
        switch (value)
        {
            case TypeElement.Geocode:
                serializer.Serialize(writer, "geocode");
                return;
            case TypeElement.StreetAddress:
                serializer.Serialize(writer, "street_address");
                return;
        }
        throw new Exception("Cannot marshal type TypeElement");
    }

    public static readonly TypeElementConverter Singleton = new TypeElementConverter();
}

GooglePlaceModel的来源:https://app.quicktype.io