[SalesForce] JSONParser.getText() results in null but not interpreted as null in if statements

I am parsing JSON that has field 'next_page'. If this field is null, I do not want to enqueue another HTTP request to fetch that page.

However, in this code, parser.getText() is debugging as null, but not evaluating as null in the if statement.

          if(parser.getText() == 'next_page'){
              parser.nextToken();
              system.debug(parser.getCurrentToken());
                if(parser.getText() != null){
                    System.debug(parser.getText());
                    System.enqueueJob(new fetchURL(parser.getText()));
                }
          }

If I run this code, I see that my debug statement is null, but it is not being evaluated as null in the previous if statement.

I can workaround the issue with:

          if(parser.getText() == 'next_page'){
              parser.nextToken();
              if(parser.getCurrentToken() == JSONToken.VALUE_STRING){
                if(!String.isBlank(parser.getText())){
                    System.debug(parser.getText());
                    System.enqueueJob(new fetchURL(parser.getText()));
                }
              }
          }

I thought the issue might be that Salesforce doesn't allow text fields to be null, but picks up an empty field with String.isBlank however this results in the same problem – null is debugging as null, but not evaluating to null:

if(parser.getText() == 'next_page'){
              parser.nextToken();
              system.debug(parser.getCurrentToken());
                if(!String.isBlank(parser.getText()){
                    System.debug(parser.getText());
                    System.enqueueJob(new fetchURL(parser.getText()));
                }
          }

I've also tried:

      if(parser.getText() == 'next_page'){
              parser.nextToken();
              system.debug(parser.getCurrentToken());
              String parserString = parser.getText();
                if(parserString != null){
                    System.debug(parser.getText());
                    System.enqueueJob(new fetchURL(parser.getText()));
                }
          }

but it seems to assign null to parserString and then not evaluate parserString as null.

Any thoughts? Suggestions? I'm at a loss…

EDIT:

Here is Apex that shows the issue.

    String jsonString = '{"next_page":null,"per_page":30,"page_count":22,"count":654}';

    JSONParser parser = JSON.createParser(jsonString);
    while(parser.nextToken() != null){
        if(parser.getCurrentToken() == JSONToken.FIELD_NAME){
        if(parser.getText() == 'next_page'){
            parser.nextToken();
            system.debug(parser.getText());
            String parserString = parser.getText();
            if(parser.getText() != null){
                System.debug(parser.getText());
            }
        }
    }
}

Best Answer

Use VALUE_NULL token

getText()

Returns the textual representation of the current token or null if there's no current token.

Since you explicitly were calling getText() without checking for null it will convert the null to a text value

String jsonString = '{"next_page":null,"per_page":30,"page_count":22,"count":654}';
JSONParser parser = JSON.createParser(jsonString);
while(parser.nextToken() != null){
    if(parser.getCurrentToken() == JSONToken.FIELD_NAME){
        if(parser.getText() == 'next_page'){
            JSONToken tok = parser.nextToken();
            System.debug('The Token: ' + tok);
            system.debug('First Text Debug' + parser.getText());
            String parserString = parser.getText();
            if(tok != JSONToken.VALUE_NULL){
                System.debug('Inside If test: ' + parser.getText());
            }
        }
    }
}

or simply

String jsonString = '{"next_page":null,"per_page":30,"page_count":22,"count":654}';
JSONParser parser = JSON.createParser(jsonString);
while(parser.nextToken() != null){
    if(parser.getCurrentToken() == JSONToken.FIELD_NAME){
        if(parser.getText() == 'next_page'){
            if(parser.nextToken() != JSONToken.VALUE_NULL){
                System.debug('Inside If test: ' + parser.getText());
            }
        }
    }
}

I rarely user parser unless there are many reserved keywords that I can't easily modify and deserialize. In your case you could simply deserialize into a Map or an Apex class and it would behave as expected

System.debug(JSON.deserializeUntyped(jsonString));

outputs

{count=654, next_page=null, page_count=22, per_page=30}

Much easier to handle