2016-08-22 48 views
0

使用谷歌的地理編碼API,在使用PHP我我可以用這個做:DELPHI谷歌的地理編碼JSON分析器

$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?我嘗試這一點,但有例外

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); 
+0

你得到什麼異常?其餘的相關代碼在哪裏? –

+0

我得到了'訪問違規地址',REST結果爲 [link](https://maps.googleapis.com/maps/api/geocode/json?latlng=-6.408107,107.468262&key=AIzaSyCUzlhl-ibUJsKCwWDwsZqjiW7EP_On30g&sensor=false) 我使用'TrestClient'和'Restresponse' –

+0

訪問衝突在什麼地址等?這些數字確實意味着什麼。你是否已經開始調試以查看這些任務之一是否返回'nil'?那會造成這樣的例外。哪一行你會得到例外? –

回答

3

你在你的PHP代碼中訪問JSON results元素是一個數組類型。然而,在你的Delphi代碼中,你試圖以對象的形式訪問它。這會導致arrayjson返回nil,並且當您嘗試訪問arrayjson時,由於它不存在,您會得到一個Access Violation例外。

相反,您應該將第一個results元素作爲數組讀取。然後,讀取該數組中的第一個(0)元素,或者遍歷所有元素 - 取決於需要。

-1

見在https://github.com/hgourvest/superobject

這個庫更容易使用(比較你的源代碼和礦),是普遍比較測試和更可靠的代碼示例(與德爾福只是讓搜索有關問題捆綁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 
更好

將是類似的東西(DID未選中,只是一個快速草案):

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; 
+1

這裏您建議提問者在不同的JSON解析器上引入第三方依賴關係。您是否暗示提問者正在使用的JSON解析器無法解析此JSON?請清楚說明。如果你打算建議提問者需要一個新的圖書館,你應該爲此提供動機。 –

+0

主題入門者並沒有將他的問題限制爲使用特定的庫,更多的是因爲他的經驗不足表明他並沒有爲DBX JSON綁定很多代碼,所以任何庫都適合。 –

+0

新手用戶能夠成功安裝一些第三方庫的前景?這確實是一個不好的建議, –

-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; 
+2

再次,不必要地提供OP來使用另一個第三方JSON庫。這裏提供使用'SuperObject'的其他答案實際上是兩次因此而下調了兩次。此外,「非常容易」更多的代碼...? –

+0

傑裏,也許你必須先閱讀這個問題,它不問如何使用DBXJson,但問如何解析json的內容!當DBXjson只是最差的設計json解析器和最慢的我從未見過的時候(大約比alcinoe或superobject慢100倍或者其他任何例子和沒有實例)時,解釋如何使用DBXJson是很愚蠢的。另外你在哪裏看到非常多的代碼?沿着= aJSONDoc.ChildNodes ['results']。ChildNodes [0] .ChildNodes ['geometry']。ChildNodes ['location']。ChildNodes ['lng']。float是更多的代碼嗎?請給與dbxjson相當的! – loki

+0

OP發佈了6行代碼,只有一個需要更正的小錯誤。你有184行代碼。如果我把我的舊車帶給你,並說它有一個癟胎,你會讓我購買一輛完全不同的車,而不是修理爆胎嗎?這當然是個好主意,但這不是問題所在。 –