在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自动完成文本框)
答案 0 :(得分:4)
因为外部对象具有两个属性,即“预测”和“状态”。您正在查看外部对象中“预测”数组的元素。尝试以下方法:
JObject jObj = (JObject)JsonConvert.DeserializeObject(content);
JArray predictions = (JArray)jObj["predictions"];
Debug.Write(predictions.Count);
答案 1 :(得分:1)
反序列化JSON的最完整方法是创建一个GooglePlaceModel
类,该类包含JSON响应中的所有属性。
添加GooglePlaceModel后,您可以使用JsonConvert.DeserializeObject
将JSON string
转换为GooglePlaceModel
public GooglePlaceModel DeserializeGooglePlaceJson(string json)
{
return JsonConvert.DeserializeObject<GooglePlaceModel>(json);
}
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