反序列化Google地图Geocode JSON信息

时间:2016-09-01 16:00:59

标签: .net json vb.net json.net

我正在尝试反序列化Google地图地理编码信息。我很接近,但我错过了一些东西。

这是JSON输出

{
"results" : [
  {
     "address_components" : [
        {
           "long_name" : "1600",
           "short_name" : "1600",
           "types" : [ "street_number" ]
        },
        {
           "long_name" : "Amphitheatre Pkwy",
           "short_name" : "Amphitheatre Pkwy",
           "types" : [ "route" ]
        },
        {
           "long_name" : "Mountain View",
           "short_name" : "Mountain View",
           "types" : [ "locality", "political" ]
        },
        {
           "long_name" : "Santa Clara County",
           "short_name" : "Santa Clara County",
           "types" : [ "administrative_area_level_2", "political" ]
        },
        {
           "long_name" : "California",
           "short_name" : "CA",
           "types" : [ "administrative_area_level_1", "political" ]
        },
        {
           "long_name" : "United States",
           "short_name" : "US",
           "types" : [ "country", "political" ]
        },
        {
           "long_name" : "94043",
           "short_name" : "94043",
           "types" : [ "postal_code" ]
        }
     ],
     "formatted_address" : "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
     "geometry" : {
        "location" : {
           "lat" : 37.4224764,
           "lng" : -122.0842499
        },
        "location_type" : "ROOFTOP",
        "viewport" : {
           "northeast" : {
              "lat" : 37.4238253802915,
              "lng" : -122.0829009197085
           },
           "southwest" : {
              "lat" : 37.4211274197085,
              "lng" : -122.0855988802915
           }
        }
     },
     "place_id" : "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
     "types" : [ "street_address" ]
  }
 ],
   "status" : "OK"
}

以下是我的课程:

 Public Class AddressComponent

    Public Property LongName As String
    Public Property ShortName As String
    Public Property Types As String()

End Class

Public Class Location

    Public Property Lat As Double
    Public Property Lng As Double

End Class

Public Class Northeast

    Public Property Lat As Double
    Public Property Lng As Double

End Class

Public Class Southwest

    Public Property Lat As Double
    Public Property Lng As Double

End Class

Public Class Viewport

    Public Property Northeast As Northeast
    Public Property Southwest As Southwest

End Class

Public Class Geometry

    Public Property Location As Location
    Public Property LocationType As String
    Public Property Viewport As Viewport

End Class

Public Class Result

    Public Property AddressComponents As AddressComponent()
    Public Property FormattedAddress As String
    Public Property Geometry As Geometry
    Public Property PlaceId As String
    Public Property Types As String()

End Class

Public Class GeocodeClass

    Public Property Results As Result()
    Public Property Status As String

End Class

这是我的代码,我一直在搞乱

 Try

        Dim url As String = "https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=KEY_OMITTED"
        Dim wc As New WebClient()
        Dim json = DirectCast(JsonConvert.DeserializeObject(wc.DownloadString(url)), JObject)

        Dim formattedaddress = json("results").SelectMany(Function(x) x("address_components")).FirstOrDefault(Function(t) t("types").First().ToString() = "country")
        'Dim country = json("results").SelectMany(Function(x) x("address_components")).FirstOrDefault(Function(t) t("types").First().ToString() = "country")
        Dim addressinfo As GeocodeClass = JsonConvert.DeserializeObject(Of GeocodeClass)(json)

        TextBox2.Text = formattedaddress.ToString

    Catch ex As Exception

    End Try

End Sub

我可以从“country”字符串中获取输出。我的目标是发出请求并将数据插入数据库。我很接近,但我还是很迷茫。有人可以向我推动一个方向吗? JSON是一个新概念,很多例子都在C#中,不幸的是vb.net对我来说更为熟悉。

1 个答案:

答案 0 :(得分:1)

几乎已经将所有内容反序列化为一个对象,但你不需要对该字符串进行任何的预处理。您还在为您创建的一个机器人类中“修复”了太多东西。

如果查看json,它会清楚地显示一个名为address_components的属性 - 当您将其更改为AddressComponents时,这些部分将返回Nothing / null,因为属性似乎缺失(它们是!)。这同样适用于long_nameLongName

可以更改类名,但不能更改属性。为此,请使用JsonProperty属性:

<JsonProperty("lat")>
Public Property Latitude As Single

这基本上会创建一个别名,因此反序列化程序可以使用"lat"并让您可以自由使用Latitude

此外,在为您创建类(甚至是VS)时,所有机器人的效率都有点低。您可能已经注意到LocationNortheastSouthwest是相同的。这意味着您可以为所有这些使用相同的类。修改后的课程请注意我单独留下了一些属性名称,如“results”:

Public Class GeocodeClass
    Public Property results As Result()
    Public Property status As String
End Class

Public Class Result
    <JsonProperty("address_components")>
    Public Property AddressComponents As AddressComponents()
    <JsonProperty("formatted_address")>
    Public Property FormattedAddress As String
    <JsonProperty("Geometry")>
    Public Property geometry As Geometry
    Public Property place_id As String
    Public Property types As String()
End Class

Public Class Geometry
    Public Property location As Location
    Public Property location_type As String
    Public Property viewport As Viewport
End Class

' class for Location, ViewPort.Northeast, ViewPort.southwest
Public Class Location
    <JsonProperty("lat")>
    Public Property Lat As Single
    <JsonProperty("lng")>
    Public Property Lng As Single
End Class

Public Class Viewport
    <JsonProperty("northeast")>
    Public Property Northeast As Location
    <JsonProperty("southwest")>
    Public Property Southwest As Location
End Class

Public Class AddressComponents
    <JsonProperty("long_name")>
    Public Property LongName As String
    <JsonProperty("short_name")>
    Public Property ShortName As String
    Public Property types As String()
End Class

然后反序列化:

Dim jstr = ....the json from whereever
Dim geoInfo = JsonConvert.DeserializeObject(Of GeocodeClass)(jstr)

' == "California"
Console.WriteLine(geoInfo.results(0).AddressComponents(4).LongName)

最外层的课程中没有太多信息,它还创建了一个导航层。摆脱它的一种方法:

Dim geoAddress() As Result            ' a bad Type name
Dim jobj = JObject.Parse(jstr)
If jobj("status").ToString = "OK" Then
    geoAddress = JsonConvert.DeserializeObject(Of Result())(jobj("results").ToString())
End If

' also prints "California"
Console.WriteLine(geoAddress(0).AddressComponents(4).LongName)

如果状态(在这种情况下不是“状态”)是正常的,那么它只是将结果(而不是“结果”)部分反序列化为一个数组,这样您就不必再使用geoInfo.前言了。第二,您不再需要GeocodeClass