使用谷歌地理编码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);
答案 0 :(得分:3)
您在PHP代码中访问的JSON results
元素是一种数组类型。但是,在您的Delphi代码中,您尝试将其作为对象进行访问。这会导致arrayjson
返回nil
,当您尝试访问arrayjson
时,由于它不存在,您会收到Access Violation
例外。
相反,您应该将第一个results
元素作为数组读取。然后,读取该数组中的第一个(0
)元素,或者遍历所有元素 - 具体取决于需要。
答案 1 :(得分:-1)
请参阅https://github.com/hgourvest/superobject
上的代码示例这个库更容易使用(比较你的源代码和我的源代码),并且通常更加经过测试和更可靠(只搜索有关Delphi捆绑的DBX JSON的问题),这在最近的Delphi中很常见。框“图书馆。
简单(但如果您需要多个数据项,而不是单个数据项,则不是非常优化))方法就像
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;