0

I'm currently working on a small app, to allow to better understand RESTful Webservices and how to consume them. The app connects to a RESTful API, and I need to find a way to display the JSON response onto a VF page.

The JSON response is an array, which is deserialized into a List for a wrapper class. However, when I call the data from the VF page, it does absolutely nothing and no errors are displayed, despite having a re-render function.

Am I calling the data correctly? Or does it have to be populated into a Map?

Here is my code:

JSON Response Snippet

[
    {
        "territoryId": "999991",
        "territoryName": "999991-Test",
        "startDate": "2018-01-01T00:00:00Z",
        "endDate": "9999-12-31T00:00:00Z",
        "recordIndex": 1
    },
    {
        "territoryId": "139445",
        "territoryName": "ABILENE TX DIAB PC1 139445",
        "startDate": "2016-07-01T00:00:00Z",
        "endDate": "9999-12-31T00:00:00Z",
        "recordIndex": 2
    },
]

Call Out Class

public class HAPI_callOut {

    public HAPI_TerrByCount_wrapper wrapper {get; set;}

    public void deserialize() {

        HttpRequest request = new HttpRequest();

        request.setEndpoint('callout:HAPI_CallOut/territories-by-country/US');
        request.setMethod('GET');
        request.setTimeout(120000);

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

        List<HAPI_TerrByCount_wrapper> wrapper = (List<HAPI_TerrByCount_wrapper>)JSON.deserialize(response.getBody(), List<HAPI_TerrByCount_wrapper>.class);
    }
}

Wrapper Class

public class HAPI_TerrByCount_wrapper {

    public class TerritoriesByCountry {

        public String territoryId {get; set;}
        public String territoryName {get; set;}
        public String startDate {get; set;}
        public String endDate {get; set;}
        public Integer recordIndex {get; set;}
    }

    public List<TerritoriesByCountry> terrByCountList {get; set;}

}

Visualforce Page

    <apex:page controller="HAPI_callOut">
    <apex:form>
        <apex:pageBlock title="Alignment Territories By Country Data">
            <apex:pageBlockButtons>
                <apex:commandButton value="Get Data!" action="{!deserialize}" reRender="TerrByCountBlock"/>
            </apex:pageBlockButtons>
            <apex:pageBlockSection id="TerrByCountBlock" columns="1">
                <apex:repeat value="{!wrapper.terrByCountList}" var="territory">
                    <apex:pageBlockSection columns="3">
                        <apex:facet name="header"> Territory ID {!territory.territoryId}</apex:facet>
                        <apex:pageBlockSectionItem>
                            <apex:outputLabel value="Territory Name" for="territoryName" />
                            <apex:outputText value="{!territory.territoryName}" id="territoryName" />
                        </apex:pageBlockSectionItem>
                        <apex:pageBlockSectionItem>
                            <apex:outputLabel value="Start Date" for="startDate" />
                            <apex:outputText value="{!territory.startDate}" id="startDate" />
                        </apex:pageBlockSectionItem>
                        <apex:pageBlockSectionItem>
                            <apex:outputLabel value="End Date" for="endDate" />
                            <apex:outputText value="{!territory.endDate}" id="endDate" />
                        </apex:pageBlockSectionItem>
                    </apex:pageBlockSection>
                </apex:repeat>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Thank you!

Update

Callout Class

public class HAPI_callOut {

    public List<HAPI_TerrByCount_wrapper> wrapper {get; set;}

    public void deserialize() {

        HttpRequest request = new HttpRequest();

        request.setEndpoint('callout:HAPI_CallOut/territories-by-country/US');
        request.setMethod('GET');
        request.setTimeout(120000);

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

        wrapper = (HAPI_TerrByCount_wrapper)JSON.deserialize(response.getBody(), HAPI_TerrByCount_wrapper.class);
    }
}

Error: Illegal assignment from HAPI_TerrByCount_wrapper to List

1 Answer 1

1

You're shadowing your Visualforce-accessible wrapper property with a local variable declaration:

    List<HAPI_TerrByCount_wrapper> wrapper = (List<HAPI_TerrByCount_wrapper>)JSON.deserialize(response.getBody(), List<HAPI_TerrByCount_wrapper>.class);

You need to remove the declaration (List<HAPI_TerrByCount_wrapper>) from your deserialize() method, because the local variable goes out of scope at the end of the method, but your property's value is never set.

Additionally, you need to make sure the type of your instance variable and the type of your deserializing code are in sync with one another. This is a little confusing (and definitely tripped me up, if you review the edit history of this answer!) because you're trying to deserialize a single HAPI_TerrByCount_wrapper object that contains a List<HAPI_TerrByCount_wrapper.TerritoriesByCountry>. However, your JSON can't directly be deserialized into HAPI_TerrByCount_wrapper or List<HAPI_TerrByCount_wrapper>, because that type has another layer of property declaration in the form of its instance variable terrByCountList, which is not represented in the JSON.

What you'll need to do ultimately is deserialize a List<HAPI_TerrByCount_wrapper.TerritoriesByCountry> and assign that list to your wrapper.terrByCountList property.

This will prevent a "‘{‘ is expected, but the JSON response is starts with an array ‘[‘" error, because you're deserializing the correct type.

(I'm sorry for the confusion - I initially overlooked the fact that you had a wrapper class around the list that actually mapped to the JSON).

9
  • But if I remove the declaration of a list and just have wrapper assigned to the deserialised data, I’ll get an error saying that ‘{‘ is expected, but the JSON response is starts with an array ‘[‘
    – Adil Khan
    Mar 19, 2018 at 9:20
  • Please see my updated answer - there is also a type mismatch here.
    – David Reed
    Mar 19, 2018 at 10:54
  • Hi @David I've made the following changes from what I understood, but I'm getting an error. See my post for updates, please!
    – Adil Khan
    Mar 19, 2018 at 13:16
  • 1
    Yes, see my update - you are almost there! You just need to make sure your types are consistent throughout your code. Apex, unlike some other languages (like Python) has strict, static typing discipline, so you always have to be explicit and consistent in how you use data types.
    – David Reed
    Mar 19, 2018 at 13:25
  • 1
    Got it! Thank you very much for your help and clear explanations!
    – Adil Khan
    Mar 19, 2018 at 13:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .