Pascal3366
Pascal3366

Reputation: 101

NullPointerException while trying to read JSON and trying to convert it to a POJO (deserialization)

Our goal is to: parse a json file and deserialize it into a java POJO

The stacktrace looks like this:

16:39:21,628 ERROR [stderr] (default task-1) java.lang.NullPointerException
16:39:21,628 ERROR [stderr] (default task-1)    at deployment.webservice_child.war //ProfileDeserializer.deserialize(ProfileDeserializer.java:31)
16:39:21,628 ERROR [stderr] (default task-1)    at deployment.webservice_child.war //ProfileDeserializer.deserialize(ProfileDeserializer.java:16)

The files we are trying to parse look like this:

{
  "properties": {
    "anon": {
      "/brief/versicherungsnehmer/vorname": true,
      "/brief/versicherungsnehmer/nachname": true
    }
  }
}

Our Json Parser class called JSONMuncher looks like this:

public class JSONMuncher {

    private final ObjectMapper objectMapper;

    public JSONMuncher() {
        this.objectMapper = createObjectMapper();
    }

    public ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    private static ObjectMapper createObjectMapper() {
        SimpleModule module = new SimpleModule()
                .addSerializer(Properties.class, new ProfileSerializer())
                .addDeserializer(Properties.class, new ProfileDeserializer());

        return new ObjectMapper(new JsonFactory()
                .disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT))
                .registerModule(module);
    }
    public Object readConfig(String filepath) {
        try {
            ObjectMapper mapper = createObjectMapper();
            SimpleModule module = new SimpleModule();
            mapper.configure(Feature.AUTO_CLOSE_SOURCE, true);
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            // do not serialize null value fields
            mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
            module.addSerializer(Properties.class, new ProfileSerializer());
            module.addDeserializer(Properties.class, new ProfileDeserializer());
            mapper.registerModule(module);

            InputStream is = new FileInputStream(filepath);
            System.out.println("[DEBUG!!!!!!!!!111!!!]: " + is.read());
            Properties anon = mapper.readValue(is, Properties.class);
            
            System.out.println(anon.getVorname());
            System.out.println(anon.getNachname());

            return anon;
        } catch (IOException e) {
            System.out.println("Beep Boop Err!!! 🤖");
            e.printStackTrace();
        }

        return null;
    }
}

This is our ProfileSerializer Class:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;

public class ProfileSerializer extends StdSerializer<Properties> {

    public ProfileSerializer() {
        this(null);
    }

    public ProfileSerializer(Class<Properties> src) {
        super(src);
    }

    @Override
    public void serialize(Properties property, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();

        if (property != null) {
            gen.writeObjectField("vorname", property.getVorname());
            gen.writeObjectField("nachname", property.getNachname());
        }

        gen.writeEndObject();
    }
}

This is our ProfileDeserializer Class:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;

@JsonDeserialize(using = Properties.class)
public class ProfileDeserializer extends com.fasterxml.jackson.databind.JsonDeserializer<Properties> {

    public ProfileDeserializer() {
        this(null);
    }

    public ProfileDeserializer(Class<?> vc) {
        super();
    }

    @Override
    public Properties deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        JsonNode profileNode = jsonParser.getCodec().readTree(jsonParser);
        Properties property = new Properties();
        property.setVorname(profileNode.get("vorname").booleanValue());
        property.setNachname(profileNode.get("nachname").booleanValue());
        //property.un

        return property;
    }

}

And this is the Properties class:

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
//import org.codehaus.jackson.map.annotate.JsonDeserialize;

import java.io.IOException;
import java.util.Map;


public class Properties extends com.fasterxml.jackson.databind.JsonDeserializer<Properties> {
    private boolean vorname;
    private boolean nachname;

    public void setVorname(boolean vorname) {
        this.vorname = vorname;
    }

    public void setNachname(boolean nachname) {
        this.nachname = nachname;
    }

    public boolean getVorname() {
        return this.vorname;
    }

    public boolean getNachname() {
        return this.nachname;
    }

    @SuppressWarnings("unchecked")
    @JsonProperty("anon")
    private void unpackNested(Map<Boolean, Object> anon) {
        //this.vorname = (boolean) anon.get("/brief/versicherungsnehmer/vorname");
        //this.nachname = (boolean) anon.get("/brief/versicherungsnehmer/nachname");
        Map<Boolean,Boolean> vorname = (Map<Boolean,Boolean>) anon.get("/brief/versicherungsnehmer/vorname");
        Map<Boolean,Boolean> nachname = (Map<Boolean,Boolean>) anon.get("/brief/versicherungsnehmer/nachname");

        this.vorname = (boolean) vorname.get("vorname");
        this.nachname = (boolean) nachname.get("nachname");
        //Map<Boolean,Boolean> owner = (Map<Boolean,Boolean>)anon.get("owner");
        //this.ownerName = owner.get("name");
    }

    @Override
    public Properties deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        JsonNode profileNode = jsonParser.getCodec().readTree(jsonParser);
        Properties property = new Properties();
        property.setVorname(profileNode.get("vorname").booleanValue());
        property.setNachname(profileNode.get("nachname").booleanValue());
        //property.un

        return property;
    }

    /*@Override
    public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        return null;
    }*/
}

The Properties class is used to store the json values in POJOs.

We tried:

Edit: I just tried out printing all the fields inside profileNode and it looks like the nodes that should exist because they exist in the json are in fact not present:

09:22:07,049 INFO  [stdout] (default task-1) Child nodes: dokumenttyp
09:22:07,049 INFO  [stdout] (default task-1) Child nodes: sprache
09:22:07,049 INFO  [stdout] (default task-1) Child nodes: vertragsdaten
09:22:07,064 INFO  [stdout] (default task-1) Child nodes: sachbearbeiter
09:22:07,064 INFO  [stdout] (default task-1) Child nodes: versicherungsnehmer
09:22:07,064 INFO  [stdout] (default task-1) Child nodes: bankverbindung
09:22:07,064 INFO  [stdout] (default task-1) Child nodes: person

Upvotes: 1

Views: 1625

Answers (1)

Pascal3366
Pascal3366

Reputation: 101

Ok so I was able to fix this issue and getting the correct values by modifying my deserialize() function like this:

@Override
    public Properties deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
       JsonNode profileNode = 
          jsonParser.getCodec().readTree(jsonParser);
       Properties property = new Properties();
        
   System.out.println(profileNode.get("properties").get("anon").get("/brief/versicherungsnehmer/vorname").booleanValue());
        property.setVorname(profileNode.get("properties").get("anon").get("/brief/versicherungsnehmer/vorname").booleanValue());

 System.out.println(profileNode.get("properties").get("anon").get("/brief/versicherungsnehmer/nachname").booleanValue());
        property.setNachname(profileNode.get("properties").get("anon").get("/brief/versicherungsnehmer/nachname").booleanValue());

return property;

}

Upvotes: 2

Related Questions