環境はDelphi11.3 Enterpriseで、FMXのTRESTRequestで、駅すぱあとのAPI(駅名=橋)を呼び出し、
結果をTRESTResponseで受け取っています。JSONは次の通りです。
{
"ResultSet": {
"apiVersion": "1.27.0.0",
"max": "1",
"offset": "1",
"engineVersion": "202304_03a",
"Point": {
"Station": {
"code": "23281",
"Name": "橋本(神奈川県)",
"Type": "train",
"Yomi": "はしもと"
},
"Prefecture": {
"code": "14",
"Name": "神奈川県"
},
"GeoPoint": {
"longi": "139.20.51.0",
"lati": "35.35.30.0",
"longi_d": "139.3475",
"lati_d": "35.591667",
"gcs": "tokyo"
}
}
}
}
※検索結果が複数件ヒットする場合は、上記のJSONのPointより下(Stationから)がネストされます
受け取ったJSONから必要な情報はNameの値だけなので、次の通りコーディングしました。
procedure TForm1.Analize(res: TRESTResponse);
var
JSONObj: TJSONObject;
PointArray: TJSONArray;
staName: String;
begin
JSONObj := res.JSONValue as TJSONObject;
PointArray := (JSONObj.GetValue('ResultSet') as TJSONObject).GetValue('Point') as TJSONArray;
for var i := 0 to PointArray.Count - 1 do
begin
staName := PointArray.Items[i].GetValue<TJSONObject>('Station').GetValue('Name').Value;
ShowMessage(staName);
end;
end;
これを実行しますと、PointArrayを取得するところで、EInvalidCast例外が発生してしまいます。
但し、検索結果が複数件になる場合は、例外は発生しません。
何か誤っている様でしたら理由を教えて頂けませんでしょうか。
尚、RESTデバッガを使用し、JSONルートにResultSet.Pointを指定すると、結果が1件でも複数件でも
正しく取得されます。
Pointが配列か配列でないかを確認して分岐処理すれば良いのかもです。
procedure TForm1.Button1Click(Sender: TObject);
var jv1:TJSONValue;
jv2:TJSONValue;
st:String;
i:Integer;
begin
jv1:=TJSONObject.ParseJSONValue(Memo1.Lines.Text) as TJsonValue;
jv1:=jv1.GetValue<TJsonValue>('ResultSet');
jv1:=jv1.GetValue<TJsonValue>('Point');
if jv1 is TJSONArray then //ここで配列かどうかを判断
begin
for i := 0 to TJsonArray(jv1).Count-1 do
begin
jv2:=TJsonArray(jv1).Items[i];
jv2:=jv2.GetValue<TJSONValue>('Station');
st:=jv2.GetValue<String>('Name');
showmessage(st);
end;
end
else
begin
jv1:=jv1.GetValue<TJsonObject>('Station');
st:=jv1.GetValue<String>('Name');
showmessage(st);
end;
end;
はずしていたらすいません。
mamさん、有難うございます。
ご提示頂いた通りのコードで上手く取得できました。
配列か否かを判定するところがポイントだったのですね。
大変勉強になりました。
ツイート | ![]() |