DELPHI谷歌GEOCODE Json解析器

时间:2016-08-22 03:15:58

标签: json delphi google-geocoder

使用谷歌地理编码API,当我使用PHP时,我可以这样做:

$request = file_get_contents("https://maps.googleapis.com/maps/api/geocode/json?latlng=-6.408107,107.468262&key=AIzaSyCUzlhl-ibUJsKCwWDwsZqjiW7EP_On30g&sensor=false");
$json = json_decode($request, true);
echo $json['results'][0]['address_components'][0]['long_name'];
echo $json['results'][0]['address_components'][1]['long_name'];

现在,DELPHI怎么办?我试试这个,但得到了EXCEPTION

  myjson:=RESTResponse1.Content;
  JSONObject := TJSONObject.ParseJSONValue(myjson) as TJSONObject;
  JSONObject2 := JSONObject.GetValue('results') as TJSONObject;
  arrayjson := JSONObject2.GetValue('address_components') as TJSONArray;
  currcond := arrayjson.Items[0] as TJSONObject;
  showmessage(currcond.GetValue('long_name').Value);

3 个答案:

答案 0 :(得分:3)

您在PHP代码中访问的JSON results元素是一种数组类型。但是,在您的Delphi代码中,您尝试将其作为对象进行访问。这会导致arrayjson返回nil,当您尝试访问arrayjson时,由于它不存在,您会收到Access Violation例外。

相反,您应该将第一个results元素作为数组读取。然后,读取该数组中的第一个(0)元素,或者遍历所有元素 - 具体取决于需要。

答案 1 :(得分:-1)

请参阅https://github.com/hgourvest/superobject

上的代码示例

这个库更容易使用(比较你的源代码和我的源代码),并且通常更加经过测试和更可靠(只搜索有关Delphi捆绑的DBX JSON的问题),这在最近的Delphi中很常见。框“图书馆。

enter image description here

简单(但如果您需要多个数据项,而不是单个数据项,则不是非常优化))方法就像

var json: iSuperObject;

json := TSuperObject.ParseStirng( RESTResponse1.Content );

ShowMessage( json[ 'results[0].address_components[0].long_name' ].AsString );

json := nil;  // clean-up after you no more need it

更好的是这样的(没有检查,只是快速草案):

var json1, json2: iSuperObject;
    arr1, arr2: TSuperArray;
    i1, i2: integer;

json1 := TSuperObject.ParseStirng( RESTResponse1.Content );
arr1 := json1.AsArray;
for i1 := 0 to arr1.Length-1 do begin
  json2 := arr1.O[i1].O['address_components'];
  arr2  := json2.AsArray;
  for i2 := 0 to arr2.Length-1 do begin 
    ShowMessage( arr2.O[i2].S['long_name'] );
  end;
end;

json2 := nil; json1 := nil;

答案 2 :(得分:-1)

使用ALJsonDoc,您可以在此处下载:https://sourceforge.net/projects/alcinoe/

或使用svn要好得多: (svn)https://svn.code.sf.net/p/alcinoe/code/

你可以很容易地做到这一点:

function _FindLatLongU(const aQuery: String;
                                     var aID_Gmap: String;
                                     var aLatitude,
                                         aLongitude: Double;
                                     const aHighAccuracy: boolean = True): boolean;

var aHttp: Twin_HttpTaskU;
    aHTTPResponse: IHTTPResponse;
    aBytes: Tbytes;
    AResponseContentStream: TMemoryStream;
    ADecodedResponseContentStream: TStream;
    aFreeDecodedResponseContentStream: boolean;
    aJsonDoc: TalJsonDocumentU;
    S1: String;

begin

  try

    //init var
    Result := False;
    aID_Gmap := '';
    aLatitude := 999;
    aLongitude := 999;

    //create local object
    aHttp := Twin_HttpTaskU.Create;
    AResponseContentStream := TMemoryStream.Create;
    ADecodedResponseContentStream := nil;
    aFreeDecodedResponseContentStream := False;
    aJsonDoc := TalJsonDocumentU.Create(true);
    try

      //init aJsonDoc
      aJsonDoc.Options := [doNodeAutoCreate];

      //do the http request
      aHTTPResponse := aHttp.HttpClient.get('http://maps.googleapis.com/maps/api/geocode/json?'+   // json indicates output as JSON
                                             'address=' + TnetEncoding.URL.Encode(aQuery) + '&'+              // The address that you want to geocode.
                                             'sensor=false&'+                                      // Indicates whether or not the geocoding request comes from a device with a location sensor. This value must be either true or false.
                                             'language=en',
                                            AResponseContentStream); // AResponseContent

      //normally this never happen because it's raise an exception in previous step
      if aHTTPResponse.StatusCode <> 200 then exit(False);

      //decode the result if necessary
      {$if defined(_USE_ZLIB)}
      if ALSameTextU(aHTTPResponse.ContentEncoding, 'gzip') then begin
        ADecodedResponseContentStream := TDecompressionStream.Create(AResponseContentStream, 15 + 16); // 15 is the default mode.
        aFreeDecodedResponseContentStream := True;                                                     // 16 is to enable gzip mode.  http://www.zlib.net/manual.html#Advanced
      end
      else ADecodedResponseContentStream := AResponseContentStream;
      {$ELSE}
      ADecodedResponseContentStream := AResponseContentStream;
      {$ENDIF}

      //put the response in aJsonDoc
      ADecodedResponseContentStream.Position := 0;
      setlength(aBytes, ADecodedResponseContentStream.Size);
      ADecodedResponseContentStream.ReadBuffer(pointer(aBytes)^, ADecodedResponseContentStream.Size);
      S1 := Tencoding.UTF8.GetString(aBytes);  //{
                                               //   "results" : [
                                               //      {
                                               //         "address_components" : [
                                               //            {
                                               //               "long_name" : "Toledo",
                                               //               "short_name" : "Toledo",
                                               //               "types" : [ "locality", "political" ]
                                               //            },
                                               //            {
                                               //               "long_name" : "Toledo",
                                               //               "short_name" : "Toledo",
                                               //               "types" : [ "administrative_area_level_4", "political" ]
                                               //            },
                                               //            {
                                               //               "long_name" : "Vega de Toledo",
                                               //               "short_name" : "Vega de Toledo",
                                               //               "types" : [ "administrative_area_level_3", "political" ]
                                               //            },
                                               //            {
                                               //               "long_name" : "Toledo",
                                               //               "short_name" : "TO",
                                               //               "types" : [ "administrative_area_level_2", "political" ]
                                               //            },
                                               //            {
                                               //               "long_name" : "Castile-La Mancha",
                                               //               "short_name" : "CM",
                                               //               "types" : [ "administrative_area_level_1", "political" ]
                                               //            },
                                               //            {
                                               //               "long_name" : "Spain",
                                               //               "short_name" : "ES",
                                               //               "types" : [ "country", "political" ]
                                               //            }
                                               //         ],
                                               //         "formatted_address" : "Toledo, Toledo, Spain",
                                               //         "geometry" : {
                                               //            "bounds" : {
                                               //               "northeast" : {
                                               //                  "lat" : 39.88605099999999,
                                               //                  "lng" : -3.9192423
                                               //               },
                                               //               "southwest" : {
                                               //                  "lat" : 39.8383676,
                                               //                  "lng" : -4.0629256
                                               //               }
                                               //            },
                                               //            "location" : {
                                               //               "lat" : 39.8628316,
                                               //               "lng" : -4.027323099999999
                                               //            },
                                               //            "location_type" : "APPROXIMATE",
                                               //            "viewport" : {
                                               //               "northeast" : {
                                               //                  "lat" : 39.88605099999999,
                                               //                  "lng" : -3.9192423
                                               //               },
                                               //               "southwest" : {
                                               //                  "lat" : 39.8383676,
                                               //                  "lng" : -4.0629256
                                               //               }
                                               //            }
                                               //         },
                                               //         "place_id" : "ChIJ8f21C60Lag0R_q11auhbf8Y",
                                               //         "types" : [ "locality", "political" ]
                                               //      }
                                               //   ],
                                               //   "status" : "OK"
                                               //}
      aJsonDoc.LoadFromJSONString(S1);

      // "OK" indicates that no errors occurred; the address was successfully parsed and at least one geocode was returned.
      if ALSametextU(aJsonDoc.ChildNodes['status'].Text, 'OK') then begin

        // get only the first result (it's the most accurate)
        if ((aHighAccuracy) and (aJsonDoc.ChildNodes['results'].ChildNodes.Count = 1)) or
           ((not aHighAccuracy) and (aJsonDoc.ChildNodes['results'].ChildNodes.Count > 0)) then begin

          // extract ID of Google Maps, it looks like hash and must be saved as text.
          // An example: EisxMjAwMyBNYWluIFN0cmVldCwgQnJpYXJ3b29kLCBOWSAxMTQzNSwgVVNB
          aID_Gmap := aJSONDoc.ChildNodes['results'].ChildNodes[0].ChildNodes['place_id'].Text;

          //"geometry" : {
          //   "location" : {
          //      "lat" : 37.4224553,
          //      "lng" : -122.0843062
          //   },
          //   "location_type" : "ROOFTOP",
          //   "viewport" : {
          //      "northeast" : {
          //         "lat" : 37.42380428029149,
          //         "lng" : -122.0829572197085
          //      },
          //      "southwest" : {
          //         "lat" : 37.42110631970849,
          //        "lng" : -122.0856551802915
          //      }
          //   }
          //}
          with aJSONDoc.ChildNodes['results'].ChildNodes[0].ChildNodes['geometry'] do begin
            aLongitude := ALStrToFloatU(ChildNodes['location'].ChildNodes['lng'].Text, ALDefaultFormatSettingsU);
            aLatitude  := ALStrToFloatU(ChildNodes['location'].ChildNodes['lat'].Text, ALDefaultFormatSettingsU);
          end;

          //set result to true
          result := true;

        end;

      end;

    finally
      AResponseContentStream.Free;
      if aFreeDecodedResponseContentStream then aDecodedResponseContentStream.Free;
      aJsonDoc.Free;
      aHttp.Free;
    end;

  except
    result := False;
  end;

end;