如何使用Java从Google地理编码序列化和反序列化JSON对象

我正在处理使用JSON的Google地理编码响应。

JSON格式如下:

{ "status": "OK", "results": [ { "types": [ "street_address" ], "formatted_address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA", "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": "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" ] } ], "geometry": { "location": { "lat": 37.4219720, "lng": -122.0841430 }, "location_type": "ROOFTOP", "viewport": { "southwest": { "lat": 37.4188244, "lng": -122.0872906 }, "northeast": { "lat": 37.4251196, "lng": -122.0809954 } } } } ] } 

我正在尝试使用Java创建序列化和反序列化它们。 我尝试过GSON,但由于它无法在更深层次上反序列化对象,因此GSON不是一个选项。

我只是想知道是否有人有这方面的经验? 也许您已经尝试过可以解决此问题的库? 一些示例代码会很棒。

我真的不想为此编写自己的API …

用jackson

 GoogleGeoCodeResponse result = mapper.readValue(jsonInOneString,GoogleGeoCodeResponse.class); public class GoogleGeoCodeResponse { public String status ; public results[] results ; public GoogleGeoCodeResponse() { } } class results{ public String formatted_address ; public geometry geometry ; public String[] types; public address_component[] address_components; } class geometry{ public bounds bounds; public String location_type ; public location location; public bounds viewport; } class bounds { public location northeast ; public location southwest ; } class location{ public String lat ; public String lng ; } class address_component{ public String long_name; public String short_name; public String[] types ; } 

如果有人有相同的问题,您可以使用romu31提供的GoogleGeoCodeResponse:

 public class GoogleGeoCodeResponse { public String status; public results[] results; public GoogleGeoCodeResponse() { } public class results { public String formatted_address; public geometry geometry; public String[] types; public address_component[] address_components; } public class geometry { public bounds bounds; public String location_type; public location location; public bounds viewport; } public class bounds { public location northeast; public location southwest; } public class location { public String lat; public String lng; } public class address_component { public String long_name; public String short_name; public String[] types; }} 

和Gson API Ex:

  Gson gson = new Gson(); GoogleGeoCodeResponse result = gson.fromJson(jsonCoord(URLEncoder.encode(address, "UTF-8")); GoogleGeoCodeResponse.class); double lat = Double.parseDouble(result.results[0].geometry.location.lat); double lng = Double.parseDouble(result.results[0].geometry.location.lng); 

这个function得到它:

 private String jsonCoord(String address) throws IOException { URL url = new URL("http://maps.googleapis.com/maps/api/geocode/json?address=" + address + "&sensor=false"); URLConnection connection = url.openConnection(); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String inputLine; String jsonResult = ""; while ((inputLine = in.readLine()) != null) { jsonResult += inputLine; } in.close(); return jsonResult; } 

您可以随时使用http://www.jsonschema2pojo.org/ 。 它适合您,您无需手动执行此操作。


虽然问题是关于JSON序列化和反序列化,但目前还不清楚你的真正目标是什么。 您可能希望能够在Java代码中使用地理定位信息,在这种情况下,我建议几乎所有地理位置信息API都具有Java SDK /客户端。 以下是Google和SmartyStreets的链接,这是我熟悉的两项服务。

以下是Google的回购中直接复制粘贴的示例。 如您所见,它使访问数据变得非常容易。

 GeoApiContext context = new GeoApiContext().setApiKey("AIza..."); GeocodingResult[] results = GeocodingApi.geocode(context, "1600 Amphitheatre Parkway Mountain View, CA 94043").await(); System.out.println(results[0].formattedAddress); 

(完全披露:我曾在SmartyStreets工作过。)

Jackson是最好的,我使用了romu31提供的模型类,将jackson库放在类路径中并使用Spring RestTemplate直接获取GeocodeResponse。

  public class GeocodeResponse { public String status; public results[] results; public GeocodeResponse() { enter code here } } class results { public String formatted_address; public geometry geometry; public String[] types; public address_component[] address_components; } class geometry { public bounds bounds; public String location_type; public location location; public bounds viewport; } class bounds { public location northeast; public location southwest; } class location { public String lat; public String lng; } class address_component { public String long_name; public String short_name; public String[] types; } 

请注意我只将jackson库放在classpath中,我甚至不需要从jackson执行任何API方法,请参阅下面的测试代码

 RestTemplate restTemplate = new RestTemplate(); Map vars = new HashMap(); vars.put("address", "Hong Kong"); vars.put("sensor", "false"); GeocodeResponse result = restTemplate.getForObject( "http://maps.googleapis.com/maps/api/geocode/json?address={address}&sensor={sensor}", GeocodeResponse.class, vars); 

但是,这个解决方案存在一个小问题,类名和属性名称不够好。 这在某种程度上是糟糕的惯例。 我知道我们可以将类名和属性名重构为更好的约定,但这意味着需要一定的努力来实现数据marhsall逻辑。