3

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?

4
  • have you also tried the spring.jackson.default-property-inclusion=NON_ABSENT? Note that this is NON_ABSENT and not NON_NULL Commented Feb 18, 2019 at 10:10
  • Tried your suggestion with both NON_ABSENT and NON_EMPTY - still not working. Commented Feb 18, 2019 at 10:54
  • What is the name and version of library from which net.sf.json.JSONObject class comes? Commented Feb 18, 2019 at 11:10
  • <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId><version>2.4</version> Commented Feb 18, 2019 at 11:58

2 Answers 2

2

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?
Sign up to request clarification or add additional context in comments.

7 Comments

Sounds reasonably, though it didn't help. I've added a configuration class: @Configuration public class JacksonConfiguration { @Bean @Primary public ObjectMapper objectMapper() { 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); return mapper;
@Tirlipirli, I am not sure this bean will be used. Have you tried to configure it with configureMessageConverters method like in your question? I know it could be a problem with rgistering custom ObjectMapper. Please, try: In Spring Boot, adding a custom converter by extending MappingJackson2HttpMessageConverter seems to overwrite the existing converter
@Tirlipirli or Custom Jackson deserializer does not get registered in Spring or Customizing HttpMessageConverters with Spring Boot and Spring MVC. I know that sometimes it is a problem with overriding when MappingJackson2HttpMessageConverter already exists on converters list.
Looks like objectMapper() method is called - with no results and configureMessageConverters(...) is not called at all.
@Tirlipirli, that's strange. Could you try with setting consumes and produces to application/json?
|
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.