api
Salesforce
Apex

Salesforceから外部APIを叩く(JSONの解析)

ApexクラスからRandom User GeneratorのAPI(以下、RandomUserAPI)を叩き、リードに登録してみます。

※リードは潜在的な顧客として認識された人や会社を登録するためのオブジェクトなのでリードの使い方としては誤りです。テストクラスでテストデータを作るくらいのイメージでやっています。

RandomUserAPIについて

https://randomuser.me/api/にアクセスすると、以下のようなJSONが返ってきます。

{
    "results": [
        {
            "gender": "female",
            "name": {
                "title": "mademoiselle",
                "first": "olivia",
                "last": "lefebvre"
            },
            "location": {
                "street": "3819 avenue du château",
                "city": "st-barthélemy vd",
                "state": "basel-stadt",
                "postcode": 9956
            },
            "email": "olivia.lefebvre@example.com",
            "login": {
                "username": "greenmeercat253",
                "password": "opus",
                "salt": "5SGUWEbt",
                "md5": "559227b3c1722b2448e959658109a443",
                "sha1": "ef650448a47cef7e3d483cb8bf857ad1794bf0c3",
                "sha256": "0a264913c6bace08d8a6fd6c40a8dae6885042a50ae0c4add868b5570d36a65b"
            },
            "dob": "1967-12-07 06:42:54",
            "registered": "2007-05-13 04:55:23",
            "phone": "(441)-746-6416",
            "cell": "(704)-379-7611",
            "id": {
                "name": "AVS",
                "value": "756.JOKA.MGZG.65"
            },
            "picture": {
                "large": "https://randomuser.me/api/portraits/women/85.jpg",
                "medium": "https://randomuser.me/api/portraits/med/women/85.jpg",
                "thumbnail": "https://randomuser.me/api/portraits/thumb/women/85.jpg"
            },
            "nat": "CH"
        }
    ],
    "info": {
        "seed": "e9bc4458117a7c8d",
        "results": 1,
        "page": 1,
        "version": "1.1"
    }
}

デフォルトでは1人分の名前や電話番号といった情報が入りますが、How to useによると人数や出身地域を指定できるオプションがあるようなので、今回は人数、フォーマット、出身地域を指定してみます。

やってみる

コード全体

public static void insertRandomUsers() {
    HttpRequest request = new HttpRequest();
    request.setEndpoint('https://randomuser.me/api/?results=10&format=JSON&nat=us');
    request.setMethod('GET');

    Http http = new Http();
    HttpResponse response = new HttpResponse();
    response = http.send(request);

    Map<String, Object> requestBody = new Map<String, Object>();
    Integer statusCode = response.getStatusCode();
    if (statusCode == 200) {
        requestBody = (Map<String, Object>)JSON.deserializeUntyped(response.getBody());
    } else {
        System.debug('Error : ' + statusCode + ' => ' + response.getBody());
        return;
    }

    List<Lead> leadList = new List<Lead>();
    for (Object result : (List<Object>)requestBody.get('results')) {
        Map<String, Object> user = (Map<String, Object>)result;
        Map<String, Object> name = (Map<String, Object>)user.get('name');

        Lead l = new Lead();
        l.firstName = String.valueOf(name.get('first'));
        l.lastName = String.valueOf(name.get('last'));
        l.phone = String.valueOf(user.get('phone'));
        l.Company = String.valueOf(user.get('email'));

        leadList.add(l);
    }
    insert leadList;
}

GETでAPIを叩く

  • httpRequestオブジェクトに対してsetEndPoint()でURLを指定
  • httpRequestオブジェクトに対してsetMethod()でリクエストメソッドを指定
  • httpオブジェクトのsend()メソッドでhttpResponseオブジェクトが返ってくる

という流れになります。

HttpRequest request = new HttpRequest();
request.setEndpoint('https://randomuser.me/api/?results=10&format=JSON&nat=us');
request.setMethod('GET');

Http http = new Http();
HttpResponse response = new HttpResponse();
response = http.send(request);

responseBodyの解析

GETした内容から名前や電話番号を取ってきてLeadオブジェクトにセットしたいわけですが、これが非常にめんどくさいです。
やり方としてはhttpResponse.getBody()でresponseの本体が取れるので、JSON.deserializeUntyped()しつつMap<String, Object>にキャストしてあげると"result"キー、"info"キー以下の内容がList<Object>として扱えるようになります。

Map<String, Object> requestBody = (Map<String, Object>)JSON.deserializeUntyped(response.getBody());
// requestBody.keySet() : Set<String> => ('results', 'info')
// requestBody.get('results').values() : List<Object> => {'gender', 'name', 'location', ...}
// requestBody.get('info').values() : List<Object> => {'seed', 'results', 'page', 'version'}

"gender"やら"name"の値を扱うためには、List<Object>をループで回しながら、String.valueOf()で文字列に変換していくことになります。値がまた配列になっている場合はMap<String, Object>へのキャストというのをまたやってあげる必要があります。各階層について配列のキャストが必要になります。

Leadへのセット

ループのなかでinsertしないのが基本ですね。

感想

responseBodyはせめて文字列のMapとして扱えるようにしてほしいです。指定したsObjectに変換できるとかあればもっとありがたいですが。