質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Salesforce

Salesforceは、クラウド型の顧客関係管理(CRM)、営業支援(SFA)などのサービスを提供している企業。米カリフォルニア州に本社があり、日本法人は株式会社セールスフォース・ドットコムです。

Apex

Apexは、Salesforce上で動作するアプリケーション作成をサポートするアプリケーション開発プラットフォーム。プログラミング言語であるApexコードと、独自のApex WebサービスAPIなどで構成されています。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

2174閲覧

SalesforceのAPEXでDeserializeした多階層のJSONの特定の値を取得したい

fk-222

総合スコア2

Salesforce

Salesforceは、クラウド型の顧客関係管理(CRM)、営業支援(SFA)などのサービスを提供している企業。米カリフォルニア州に本社があり、日本法人は株式会社セールスフォース・ドットコムです。

Apex

Apexは、Salesforce上で動作するアプリケーション作成をサポートするアプリケーション開発プラットフォーム。プログラミング言語であるApexコードと、独自のApex WebサービスAPIなどで構成されています。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2022/12/28 17:51

前提

GoogleMapAPIでの下記レスポンスをSalesforceのAPEXを使用して配列化し、特定のvalueを取得したい

{ "results" : [ { "address_components" : [ { "long_name" : "1", "short_name" : "1", "types" : [ "premise" ] }, { "long_name" : "7", "short_name" : "7", "types" : [ "political", "sublocality", "sublocality_level_4" ] }, { "long_name" : "1丁目", "short_name" : "1丁目", "types" : [ "political", "sublocality", "sublocality_level_3" ] }, { "long_name" : "永田町", "short_name" : "永田町", "types" : [ "political", "sublocality", "sublocality_level_2" ] }, { "long_name" : "千代田区", "short_name" : "千代田区", "types" : [ "locality", "political" ] }, { "long_name" : "東京都", "short_name" : "東京都", "types" : [ "administrative_area_level_1", "political" ] }, { "long_name" : "日本", "short_name" : "JP", "types" : [ "country", "political" ] }, { "long_name" : "107-0052", "short_name" : "107-0052", "types" : [ "postal_code" ] } ], "formatted_address" : "日本、〒107-0052 東京都千代田区永田町1丁目7−1", "geometry" : { "bounds" : { "northeast" : { "lat" : 35.6718197, "lng" : 139.7418786 }, "southwest" : { "lat" : 35.671749, "lng" : 139.7417899 } }, "location" : { "lat" : 35.6717816, // 取得したい値 "lng" : 139.7418364 // 取得したい値 }, "location_type" : "ROOFTOP", "viewport" : { "northeast" : { "lat" : 35.6730461302915, "lng" : 139.7432597302915 }, "southwest" : { "lat" : 35.6703481697085, "lng" : 139.7405617697085 } } }, "place_id" : "ChIJeYgkB4aLGGAREJ71ye_H0Ak", "types" : [ "premise" ] } ], "status" : "OK" }

実現したいこと

上記構造のlocationのlat,lngを取得したい

該当のソースコード

Java

1 final String endpoint = 'https://maps.googleapis.com/maps/api/geocode/json?address=' + '東京都千代田区永田町1丁目7−1' + '&components=country:JP&key=API_KEY'; 2HttpRequest req = new HttpRequest(); 3Http h = new Http(); 4req.setMethod('GET'); 5req.setEndpoint(endpoint); 6HttpResponse res = h.send(req); 7Map<String,Object> resText = (Map<String,Object>)JSON.deserializeUntyped(res.getBody()); 8Map<String,Object> results = (Map<String,Object>)resJson.get('results'); 9//これで上記構造のresult以下は取得できた。

試したこと

・Mapでの取得は一通り試しましたが、間にListが入っていることでObject→Listのキャストがうまくいきませんでした。
・JSON.parseなどのドキュメントもありましたが、特定のキーを取得するだけなのでイテラルとして扱うのは少し違和感があります。
・Wrapperクラスでの定義も考えましたが、2階層以上だとどのように定義するかがよくわかりません。

以上よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

Salesforce も Apex も分からないのですが、 java で良いんでしょうか。
ベタなら正規表現でも取り出せますが。

java

1import java.util.regex.Matcher; 2import java.util.regex.Pattern; 3 4public class Main { 5 public static void main(String[] args) { 6 Pattern p = Pattern.compile("\"location\"\s*:\s*\\{\n\s*\"lat\"\s*:\s*([0-9.]+),\n\s*\"lng\"\s*:\s*([0-9.]+)\n\s*\\}"); 7 Matcher m = p.matcher(json); 8 while(m.find()) { 9 System.out.println("lat="+m.group(1)+", lng="+m.group(2)); 10 } 11 } 12 13 static final String json = "{\n" 14 + " \"results\" : [\n" 15 + " {\n" 16 + " \"address_components\" : [\n" 17 + " {\n" 18 + " \"long_name\" : \"1\",\n" 19 + " \"short_name\" : \"1\",\n" 20 + " \"types\" : [ \"premise\" ]\n" 21 + " },\n" 22 + " {\n" 23 + " \"long_name\" : \"7\",\n" 24 + " \"short_name\" : \"7\",\n" 25 + " \"types\" : [ \"political\", \"sublocality\", \"sublocality_level_4\" ]\n" 26 + " },\n" 27 + " {\n" 28 + " \"long_name\" : \"1丁目\",\n" 29 + " \"short_name\" : \"1丁目\",\n" 30 + " \"types\" : [ \"political\", \"sublocality\", \"sublocality_level_3\" ]\n" 31 + " },\n" 32 + " {\n" 33 + " \"long_name\" : \"永田町\",\n" 34 + " \"short_name\" : \"永田町\",\n" 35 + " \"types\" : [ \"political\", \"sublocality\", \"sublocality_level_2\" ]\n" 36 + " },\n" 37 + " {\n" 38 + " \"long_name\" : \"千代田区\",\n" 39 + " \"short_name\" : \"千代田区\",\n" 40 + " \"types\" : [ \"locality\", \"political\" ]\n" 41 + " },\n" 42 + " {\n" 43 + " \"long_name\" : \"東京都\",\n" 44 + " \"short_name\" : \"東京都\",\n" 45 + " \"types\" : [ \"administrative_area_level_1\", \"political\" ]\n" 46 + " },\n" 47 + " {\n" 48 + " \"long_name\" : \"日本\",\n" 49 + " \"short_name\" : \"JP\",\n" 50 + " \"types\" : [ \"country\", \"political\" ]\n" 51 + " },\n" 52 + " {\n" 53 + " \"long_name\" : \"107-0052\",\n" 54 + " \"short_name\" : \"107-0052\",\n" 55 + " \"types\" : [ \"postal_code\" ]\n" 56 + " }\n" 57 + " ],\n" 58 + " \"formatted_address\" : \"日本、〒107-0052 東京都千代田区永田町1丁目7−1\",\n" 59 + " \"geometry\" : {\n" 60 + " \"bounds\" : {\n" 61 + " \"northeast\" : {\n" 62 + " \"lat\" : 35.6718197,\n" 63 + " \"lng\" : 139.7418786\n" 64 + " },\n" 65 + " \"southwest\" : {\n" 66 + " \"lat\" : 35.671749,\n" 67 + " \"lng\" : 139.7417899\n" 68 + " }\n" 69 + " },\n" 70 + " \"location\" : {\n" 71 + " \"lat\" : 35.6717816,\n" // 取得したい値 72 + " \"lng\" : 139.7418364\n" // 取得したい値 73 + " },\n" 74 + " \"location_type\" : \"ROOFTOP\",\n" 75 + " \"viewport\" : {\n" 76 + " \"northeast\" : {\n" 77 + " \"lat\" : 35.6730461302915,\n" 78 + " \"lng\" : 139.7432597302915\n" 79 + " },\n" 80 + " \"southwest\" : {\n" 81 + " \"lat\" : 35.6703481697085,\n" 82 + " \"lng\" : 139.7405617697085\n" 83 + " }\n" 84 + " }\n" 85 + " },\n" 86 + " \"place_id\" : \"ChIJeYgkB4aLGGAREJ71ye_H0Ak\",\n" 87 + " \"types\" : [ \"premise\" ]\n" 88 + " }\n" 89 + " ],\n" 90 + " \"status\" : \"OK\"\n" 91 + "}"; 92}
lat=35.6717816, lng=139.7418364

真面目に構造作って Jackson でオブジェクト化するとか。

java

1import com.fasterxml.jackson.core.JsonProcessingException; 2import com.fasterxml.jackson.databind.JsonMappingException; 3import com.fasterxml.jackson.databind.ObjectMapper; 4 5public class Main { 6 7 static class GoogleGeocodeResponse { 8 static class Result { 9 static class AddressComponent { 10 public String long_name; 11 public String short_name; 12 public String[] types; 13 } 14 static class Geometry { 15 static class Position { 16 public double lat, lng; 17 } 18 static class Area { 19 public Position northeast, southwest; 20 } 21 public Area bounds; 22 public Position location; 23 public String location_type; 24 public Area viewport; 25 } 26 public AddressComponent[] address_components; 27 public String formatted_address; 28 public Geometry geometry; 29 public String place_id; 30 public String[] types; 31 } 32 public Result[] results; 33 public String status; 34 } 35 36 public static void main(String[] args) throws JsonMappingException, JsonProcessingException { 37 ObjectMapper mapper = new ObjectMapper(); 38 GoogleGeocodeResponse response = mapper.readValue(json, GoogleGeocodeResponse.class); 39 for(GoogleGeocodeResponse.Result result : response.results) { 40 System.out.println("lat="+result.geometry.location.lat+", lng="+result.geometry.location.lng); 41 } 42 } 43 44 static final String json = "{\n" 45 //データ略 46}

投稿2022/12/29 05:41

編集2022/12/29 06:16
jimbe

総合スコア13170

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fk-222

2022/12/30 09:10

正規表現で無事該当箇所取り出すことができました。 APEXのベストプラクティスが有識者によって回答されるかもしれないので、ベストアンサーに選択するのはもう少し後にさせてください。 ちなみに、APEXはほぼJavaですが、Javaの文法が丸々使用できるわけではないです。(例えばラッパークラスで内部クラスに内部クラスを持てないなど。)
jimbe

2022/12/30 14:45 編集

クラス内でクラスを定義しているのはスコープと構造表現のためだけですので、 class Position { } class Area { } class Geometry { } …と各々別に定義するのは如何でしょうか。
guest

0

SalesforceのAPEXでDeserializeした

ここは無視して、

多階層のJSONの特定の値を取得したい

の部分だけ。

locatin: <{lat=35.6717816, lng=139.7418364}>

java

1import com.fasterxml.jackson.databind.ObjectMapper; 2import org.junit.jupiter.api.Test; 3 4import java.util.List; 5import java.util.Map; 6 7public class HogeJson { 8 /** 9 */ 10 @Test 11 public void aaa() throws Exception { 12 final ObjectMapper mapper = new ObjectMapper(); 13 14 final Map<String, Object> res = mapper.readValue(json, Map.class); 15 System.out.println(res); 16 17 Object locatin = findLocation(res); 18 System.out.println("locatin: <%s>".formatted(locatin)); 19 } 20 21 /** 22 */ 23 private Object findLocation(Map<String, Object> map) { 24 final String location = "location"; 25 if (map.containsKey(location)) return map.get(location); 26 27 for (Object value : map.values()) { 28 if (value instanceof Map) { 29 final Object res = findLocation((Map) value); 30 if (res != null) return res; 31 } 32 if (value instanceof List) { 33 final Object res = findLocation((List) value); 34 if (res != null) return res; 35 } 36 } 37 38 return null; 39 } 40 41 /** 42 */ 43 private Object findLocation(List<Object> list) { 44 for (Object item : list) { 45 if (item instanceof Map) { 46 final Object res = findLocation((Map) item); 47 if (res != null) return res; 48 } 49 if (item instanceof List) { 50 final Object res = findLocation((List) item); 51 if (res != null) return res; 52 } 53 } 54 55 return null; 56 } 57 58 final String json = """ 59 { 60 "results" : [ 61 { 62 "address_components" : [ 63 { 64 "long_name" : "1", 65 "short_name" : "1", 66 "types" : [ "premise" ] 67 }, 68 { 69 "long_name" : "7", 70 "short_name" : "7", 71 "types" : [ "political", "sublocality", "sublocality_level_4" ] 72 }, 73 { 74 "long_name" : "1丁目", 75 "short_name" : "1丁目", 76 "types" : [ "political", "sublocality", "sublocality_level_3" ] 77 }, 78 { 79 "long_name" : "永田町", 80 "short_name" : "永田町", 81 "types" : [ "political", "sublocality", "sublocality_level_2" ] 82 }, 83 { 84 "long_name" : "千代田区", 85 "short_name" : "千代田区", 86 "types" : [ "locality", "political" ] 87 }, 88 { 89 "long_name" : "東京都", 90 "short_name" : "東京都", 91 "types" : [ "administrative_area_level_1", "political" ] 92 }, 93 { 94 "long_name" : "日本", 95 "short_name" : "JP", 96 "types" : [ "country", "political" ] 97 }, 98 { 99 "long_name" : "107-0052", 100 "short_name" : "107-0052", 101 "types" : [ "postal_code" ] 102 } 103 ], 104 "formatted_address" : "日本、〒107-0052 東京都千代田区永田町1丁目7−1", 105 "geometry" : { 106 "bounds" : { 107 "northeast" : { 108 "lat" : 35.6718197, 109 "lng" : 139.7418786 110 }, 111 "southwest" : { 112 "lat" : 35.671749, 113 "lng" : 139.7417899 114 } 115 }, 116 "location" : { 117 "lat" : 35.6717816, 118 "lng" : 139.7418364 119 }, 120 "location_type" : "ROOFTOP", 121 "viewport" : { 122 "northeast" : { 123 "lat" : 35.6730461302915, 124 "lng" : 139.7432597302915 125 }, 126 "southwest" : { 127 "lat" : 35.6703481697085, 128 "lng" : 139.7405617697085 129 } 130 } 131 }, 132 "place_id" : "ChIJeYgkB4aLGGAREJ71ye_H0Ak", 133 "types" : [ "premise" ] 134 } 135 ], 136 "status" : "OK" 137 } 138 """; 139} 140

投稿2022/12/29 04:09

shiketa

総合スコア4041

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問