简体   繁体   中英

How to support JSONP with Spring MVC and multiple response types

I have a method in a controller that will return HTML or JSON depending on which was asked for. Here's a stripped-down example of such a method, modeled after information on how to do this that I found in this question :

@RequestMapping(value="callback")
public ModelAndView callback(@RequestParam("c") String c) {
    Map response = new HashMap<String, String>();
    response.put("foo", "bar");
    return new ModelAndView("fake", "data", new JSONPObject(c, response));
}

I put the JSONPObject into the model because I have to in order to be able to reach it from the view that renders if HTML was requested. But this poses a problem when I'm rendering JSON with a callback:

curl 'http://localhost:8080/notes/callback.json?c=call'
{"data"call(:{"foo":"bar"})}

As you can see, because I put my data in the "data" slot in the model, when the model is rendered as JSON there's that extra wrapping. What I'm looking for is the rendered JSON (technically JSONP) to look like this:

call({"data":{"foo":"bar"}})

Can anyone see a way to get where I'm trying to go without breaking the ability to return a view that accesses the JSONPObject during rendering?

This is how I'm using JSONP with Spring MVC, just modify it according to your needs:

on Server Side:

@RequestMapping(value="/notes/callback.json", method=RequestMethod.GET)
public void jsonpCallback(@RequestParam("callback") String callback, HttpServletResponse response) {
   response.setContentType("text/javascript; charset=UTF-8");
   PrintWriter out = response.getWriter();
   out.print(callback + "(" + jsonDataString + ")");
}

On client side:

<script src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
<script type="text/javascript">

function yourfunction() {
    jQuery.getJSON("http://localhost:8080/notes/callback.json?callback=?", 
        function(data) {
            alert(data.someParam);
        });
}

</script>

I figured this out. When rendering JSON, Spring is using a MappingJacksonJsonView per my configuration. That view has a property that tells it to find the single item in the map and extract it before rendering. After setting that property, this now works.

    <property name="defaultViews">
        <list>
            <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" >
                <property name="extractValueFromSingleKeyModel" value="true" />
            </bean>
        </list>
    </property>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM