Tirlipirli
Tirlipirli

Reputation: 113

Spring boot JsonMappingException: Object is null

I have a @RestController that returns net.sf.json.JSONObject:

@PostMapping("/list")
public JSONObject listStuff(HttpServletRequest inRequest, HttpServletResponse inResponse) {
    JSONObject json = new JSONObject();
    ...
    return json;
}

When JSONObject contains null reference, the following exception is thrown:

Could not write JSON: Object is null; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Object is null (through reference chain: net.sf.json.JSONObject[\"list\"]->net.sf.json.JSONArray[0]->net.sf.json.JSONObject[\"object\"]->net.sf.json.JSONNull[\"empty\"])"

This is the legacy code that we are now cleaning up and at some point we will get rid of explicit JSON manipulations, but this will be a huge change, for now I would like to just get rid of the exception. I tried with following solutions:

  1. Define Include.NON_NULL in Spring's Object Mapper - so this piece of code in my WebMvcConfigurationSupportClass:
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) 
{
    ObjectMapper webObjectMapper = objectMapper.copy();
    webObjectMapper.setSerializationInclusion(Include.NON_NULL);
    converters.add(new MappingJackson2HttpMessageConverter(webObjectMapper)); 
}
  1. Setting following property in application.yml: spring.jackson.default-property-inclusion=non_null
  2. Checking the version of com.fasterxml.jackson - the only found in the dependency tree is 2.9.7.

None of the above helped.

Any suggestions on how to tell Spring to ignore null values in net.sf.json.JSONObjects?

Upvotes: 3

Views: 3807

Answers (2)

Tirlipirli
Tirlipirli

Reputation: 113

This is not the ideal solution, but rather a workaround. As overriding default mapper/converter behavior didn't work, instead I changed the structure of my JSONObject, so added following line during its generation:

listElt.put("object", "");

which produces: { "list" : [ { "object" : "" } ] }

This is fine only if I am not interested in the value of this field - and I am not. I personally prefer @Michał Ziober's solution - it is elegant and generic. Unfortunately doesn't work for me.

Upvotes: 0

Michał Ziober
Michał Ziober

Reputation: 38700

Include.NON_NULL does not work because JSONNull represents null but it is not null per se. From documentation:

JSONNull is equivalent to the value that JavaScript calls null, whilst Java's null is equivalent to the value that JavaScript calls undefined.

This object is implemented as a Singleton which has two methods: isArray and isEmpty where isEmpty is problematic because throws exception. Below snippet shows it's implementation:

public boolean isEmpty() {
   throw new JSONException("Object is null");
}

The best way is to define NullSerializer for JSONNull type. Below example shows how we can configure that:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.NullSerializer;
import net.sf.json.JSONArray;
import net.sf.json.JSONNull;
import net.sf.json.JSONObject;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        SimpleModule netSfJsonModule = new SimpleModule("net.sf.json");
        netSfJsonModule.addSerializer(JSONNull.class, NullSerializer.instance);

        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.registerModule(netSfJsonModule);

        JSONObject object = new JSONObject();
        object.accumulate("object", JSONNull.getInstance());

        JSONArray jsonArray = new JSONArray();
        jsonArray.add(object);

        JSONObject json = new JSONObject();
        json.accumulate("list", jsonArray);

        System.out.println(mapper.writeValueAsString(json));
    }
}

Above code prints:

{
  "list" : [ {
    "object" : null
  } ]
}

See also:

  1. Maven: missing net.sf.json-lib
  2. How do you override the null serializer in Jackson 2.0?

Upvotes: 2

Related Questions