I've been reading for A LONG WHILE now, even in the SF documentation to try to solve this problem.

I'm trying to understand how Apex works with Json and the different methods I can use so I tried to make a simple app that recieves a json response and trying to deserialize it using the Apex classes pattern I've seen all around the internet.

This is an example of the json and the part I'm trying to deserialize right now:

  "abilities": [
      "ability": {
        "name": "limber",
        "url": "https://pokeapi.co/api/v2/ability/7/"
      "is_hidden": false,
      "slot": 1
      "ability": {
        "name": "imposter",
        "url": "https://pokeapi.co/api/v2/ability/150/"
      "is_hidden": true,
      "slot": 3

I know it's not well formatted, just an example. To see the full json please refer to the endpoint in the code.

So this is the Apex class I've created:

    public class PokeApiIntegration {
    public void basicAuthCallout() {
        HttpRequest req = new HttpRequest();
        // Create a new http object to send the request object
        // A response object is generated as a result of the request  
        Http http = new Http();
        HTTPResponse res = http.send(req);
        String responseBody = res.getBody();
        //Parse jsonString
        JSONParser parser = JSON.createParser(res.getBody());

        // Advance to the next token.
        while (parser.nextToken() != null) {
            // Start at the array of Abilities.
            if (parser.getCurrentToken() == JSONToken.START_ARRAY) {
                while (parser.nextToken() != null) {
                    // Advance to the start object marker to
                    //  find next object.
                    if (parser.getCurrentToken() == JSONToken.START_OBJECT) {
                        // Read entire object.
                        Abilities abl = (Abilities)parser.readValueAs(Abilities.class);
                        system.debug('slot : ' + abl.slot);
                        system.debug('is_hidden : ' + abl.is_hidden);
                        system.debug('slot : ' + abl.abilities);
    // Inner classes used for serialization by readValuesAs(). 
    public class Abilities {
        List<Ability> abilities;
        Boolean is_hidden;
        Integer slot;
        public Abilities(List<Ability> abilities, Boolean is_hidden, Integer slot) {
            this.slot = slot;
            this.is_hidden = is_hidden;
            this.abilities = abilities.clone();
    public class Ability {
        public String name;
        public String url;

I've been looking at this part of the SF documentation https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_json_jsonparser.htm ,and trying to do the same here in my code but I'm getting two errors with it.

First one is that I can't understand why system.debug('slot : ' + abl.abilities); this line of code is debugging 'null' while these two system.debug('slot : ' + abl.slot); system.debug('is_hidden : ' + abl.is_hidden); are debugging the expected values for the slot and for the boolean 'is_hidden' value, and I think it's because the Ability class should be nested inside the Abitities class (but then I can't have a nested class inside an already nested class, sience the Abilities class in a inner class already).

Second problem is that I can't find a way to stop the while loop and I can't determine what would be a good stop for it.

enter image description here

It's looping ok the first two times but then it should stop. I was wondering if someone with more experience could help me solving this problems. Thanks a lot for reading

1 Answer 1


I feel that you may have explored this, but have you tried just deserializing into a typed list of Abilities?

You'd define your inner classes like so:

public class Ability {
    public String name;
    public String url;

public class Abilities {
    public Ability ability;
    public Boolean is_hidden;
    public Integer slot;

Then just deserialize the whole html response into the Abilities array:

public Abilities[] abilities = (Abilities[])JSON.deserialize(res.getBody(),Abilities[].class);

That's pretty much all you have to do.

Apologies if you were specifically wanting to build your own parser - normally you don't have to do this, unless your JSON has a reserved keyword in Apex.

Easiest way to build the classes is to use JSON2Apex - which can also build your parser to if you need that.

  • Thanks @Caspar ! I've ended up using Json2Apex as recommended, it was the easiest way for sure. Apr 7, 2021 at 5:13
  • 1
    It's definitely very handy! Apr 7, 2021 at 5:14
  • Just a side note; you don't have to write a parser when the JSON contains keywords, you could also string replace them in the JSON string and deserialize into an apex class. This is in my opinion still better than writing your own parser. Apr 7, 2021 at 11:39
  • Yep good point - I've done that a few times myself. Apr 7, 2021 at 19:06
  • @rael_kid It's nearly impossible to do the string replace correctly without actually parsing the JSON since you might end up replacing occurrences of your reserved word in the JSON values instead of the JSON keys. Let's say your JSON contains {"new":"new"} - how are you going to replace "new" with something else but just in the key? Salesforce needs to introduce JSON annotations like @JsonProperty to control deserialization, like Jackson has on Java, and this wouldn't be an issue.
    – Frans
    Feb 5, 2022 at 17:58

You must log in to answer this question.

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