0

I am not able to get JsonDeserializer to process null values. I have a json file I am reading from where there are just four values for my record type: Case 1, Case 2, *, or null. JsonDeserializer works fine for the first 3. However, it seems to do nothing when encountering a null. Based on the code (see my custom deserializer below), I would expected the line

text = StringUtils.upperCase(jsonParser.getText());

to either throw an exception (and thus assign text = "NULL). Or, return an empty string as per

if (StringUtils.isBlank(text))

where likewise I assign text = "NULL". However, neither of these ever happens. It seems as though the null is not processed at all (which is not possible, right?). My

System.out.println("TEXT: " + text);

always prints Case 1, Case 2, or *, but never NULL. It literally seems to skip the null entry in the file, or at least does not process it in any way that is accounted for in my code. I would be grateful for any ideas. Thank you!!

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import my.local.CustomValue;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;

public class CustomDeserializer extends JsonDeserializer<CustomValue> {
    @Override
    public CustomValue deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext)  {
       CustomValue retVal = null;

       // Get the text from the JSON
       String text = null;


       try {
          text = StringUtils.upperCase(jsonParser.getText());
       } catch (IOException e) {
          e.printStackTrace();
          text = "NULL";
       }

       System.out.println("TEXT: " + text);

       // If the text is empty or null, make it NULL
       if (StringUtils.isBlank(text)) {
          text = "NULL";
       }

       // Based on the text value, return the appropriate retVal
       switch (text) {
          case "Case 1":
              retVal = CustomValue.CASE1;
              break;

          case "Case 2":
              retVal = CustomValue.CASE2;
              break;

          case "NULL":
              retVal = CustomValue.NULL;
              break;

          case "*":
              retVal = CustomValue.WILDCARD;
              break;

          default:
              retVal = CustomValue.NULL;
              break;
        }

      return retVal;
    }
}
Timothy Clotworthy
  • 1,960
  • 2
  • 19
  • 42
  • Is input json file a valid json ? In Json, a null is represented as unquoted null as mentioned here - https://stackoverflow.com/questions/21120999/representing-null-in-json – Goro Jun 04 '20 at 13:53
  • @Goro, the format we are using is like the { "myString": null } – Timothy Clotworthy Jun 04 '20 at 14:03

1 Answers1

2

The JavaDoc of JsonDeserializer.deserialize states the following:

"... Note that this method is never called for JSON null literal, and thus deserializers need (and should) not check for it."

Jackson handles null values by itself and will not call the deserialize of the custom deserializer. To customize the value that is returned for null, you have to override the getNullValue method of the deserializer.

rmunge
  • 3,653
  • 5
  • 19
  • thanks. I am not fully comprehending. I created the following: @Override public CustomValue getNullValue(DeserializationContext ctxt) throws JsonMappingException { return ColumnValue.NULL; } . it still needs to call my deserialize somehow,. it is calling my getNullValue() (thats good). But then still not calling the deserialize. I am still not comprehending fully... – Timothy Clotworthy Jun 04 '20 at 15:40
  • You haven't shared the code that uses the JsonDeserializer. I assume that you are using ObjectMapper for deserialization and registered your JsonDeserializer for the deserialization of a specific field or type. – rmunge Jun 04 '20 at 16:02
  • When use use now ObjectMapper for deserialization it will first read the value of the property. If it is a null literal (i.e. null and not 'null') it calls getNullValue() of the registered deserializer and uses the returned value for deserialization. If the value is not null it calls the deserialize() method and uses the return value of this method for deserialization. Therefore you can completely ignore the null values in your deserializer method. – rmunge Jun 04 '20 at 16:02
  • Nvermind. I get it now. Your answer was spot on. It is working now. What I added above: @Override public CustomValue getNullValue(DeserializationContext ctxt) throws JsonMappingException { return ColumnValue.NULL; } was all i needed, and that was based on your insight. thank you – Timothy Clotworthy Jun 04 '20 at 16:10