2

there.
I have a doubt with returning JSONObjects on a Spring RESTful WebService.

Here it goes:
I have a method in my controller which I want to have it returning a JSONObject. However, when I set it's return type to JSONObject and effectively return a JSONObject, I get that following error:

HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalArgumentException: No converter found for return value of type: class org.json.JSONObject

So, I actually understand what that means, and I've been searching a answer to that issue for at least 3 days.

Here is my code:

@RequestMapping(value = "/value", method = RequestMethod.POST)
public String method(HttpServletRequest request) {
    JSONObject json = new JSONObject();
    json.put("example", "example message");

    return json.toString();
}

I trully don't know if that's gonna work when I have to consume it on the front-end (Which is going to be an external application). Do I have to return a true JSONObject? Or returning a JSONObject.toString() should work fine?

And one last thing:
Most tutorials about returning a JSONObject teaches that proccess using a model object, which I don't want to use. Is there a way of doing that without using a model object?

Thanks in advance, peeps!

Ivan Assalim
  • 59
  • 1
  • 9
  • Show the failing code. Did you annotate the method that had a problem with `JSONObject` with `@ResponseBody`? – chrylis -cautiouslyoptimistic- May 23 '16 at 02:07
  • I'll also note that you're going to unnecessary trouble; you could simply return a `Map` in this case that would work fine and would be less complicated. – chrylis -cautiouslyoptimistic- May 23 '16 at 02:10
  • @chrylis No, actually my controller is a `@RestController` so there is no need to annotate the method with `@ResponseBody`(Right?). So, I wish to have it returning a JSON because I plan to consume that response after posting to my action with JQuery(probably AJAX). – Ivan Assalim May 23 '16 at 02:23
  • That's correct, but you didn't post that. So why again are you not just returning the map? Spring will convert it for you, assuming you have JSON support included in your application (and you should be using Spring Boot, which will). – chrylis -cautiouslyoptimistic- May 23 '16 at 02:33

6 Answers6

1

I had the same issue, and the solution is unbelievably simple. I assume that you have Jackson in your dependencies, and then you can do as follows:

After you create a JSONObject you want to return, simply write: return jsonObject.toMap(), and Jackson will do the rest of the work. Don't forget to change the return type of your method to Map<String, Object>, and apply appropriate annotations: @ResponseBody on the method, or @RestController on a whole class. It depends on your needs.

In your case it will be:

@RequestMapping(value = "/value", method = RequestMethod.POST)
public @ResponseBody Map<String, Object> method(HttpServletRequest request) {
    JSONObject json = new JSONObject();
    json.put("example", "example message");

    return json.toMap();
}
itachi
  • 3,389
  • 2
  • 24
  • 29
0

Just annotate your method with @ResponseBody.

Akhil
  • 1,184
  • 1
  • 18
  • 42
0

Change class annotation to @RestController, then return model object or Map<String, Object>. You don't need to mess with JSONObject for the task.

@ResponseBody for the method, like akhill answered, is also ok but too verbose if all the controller is REST.

no id
  • 1,642
  • 3
  • 24
  • 36
  • The big problem about returning a Map is that I have my whole logic implemented as JSONObjects and I use several JSONArrays too. I have my controller annotated as a `@RestController`. Would you happen to know if I return a json.toString(), will I able to consume it on the front-end as a JSON? – Ivan Assalim May 23 '16 at 05:28
  • Why the frontend should care about how JSON is constructed? It ends up as a text anyway! The only possible concern here is mime-type. Looks like this post may be of help: http://stackoverflow.com/questions/3616359/who-sets-response-content-type-in-spring-mvc-responsebody – no id May 23 '16 at 05:42
  • Thanks for the help until here. So, based on what you just said, if I return a plain text, a string of something like this: `{"name":"Your name"}` which represents the JSON generated on the backend, I will still be able to consume it as a JSON on the front-end? I can already render the string response to the browser, the problem is: I can't find a way to consume it. – Ivan Assalim May 23 '16 at 05:55
  • I don't get the problem. You just do your $http.post("/your/url") and recieve a JS object whatever happens on the server side, as long as it doesn't give you 500 code. – no id May 23 '16 at 06:45
0

If you are using Jackson for mapping you can return an ObjectNode instead. It is Jackson's representation of a json object. There is also an ArrayNode class. If you want to use your own implementation then either write an HttpMessageConverter that allows reading and writing json or use the toString method if this actually returns a json string.

Simon Forsberg
  • 13,086
  • 10
  • 64
  • 108
0

You can also use anonymous object:

new Object() {
    public final int code = 0;

    public final List<T> data = ...;
}
softwarevamp
  • 827
  • 10
  • 14
0

It is very easy i solved this way:

@RequestMapping({"/jsontest"})
    public @ResponseBody
    Map<String, Object> jsonTest() {
        String json = "{\"name\":\"farshad\", \"age\":34 , \"list\": [ 1 , 2 , 3 ] , \"objects\": [ {\"name\":\"a\", \"age\":\"10\"} , {\"name\":\"b\", \"age\":\"20\"} , {\"name\":\"c\", \"age\":\"30\"} ] }"; 
        ObjectMapper mapper = new ObjectMapper();

        // convert JSON string to Map
        Map<String, Object> map = mapper.readValue(json, Map.class);
        return map;
    }

Dependency:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.8</version>
</dependency>

Imports:

/* Json Imports */
import com.fasterxml.jackson.databind.ObjectMapper;    
import java.util.Map;

Result: