简体   繁体   English

Spring MVC控制器中的JSON参数

[英]JSON parameter in spring MVC controller

I have 我有

@RequestMapping(method = RequestMethod.GET)
@ResponseBody
SessionInfo register(UserProfile profileJson){
  ...
}

I pass profileJson this way: 我以这种方式传递profileJson:

http://server/url?profileJson={"email": "mymail@gmail.com"}

but my profileJson object has all null fields. 但我的profileJson对象具有所有空字段。 What should I do to make spring parse my json? 我应该怎么做才能使spring解析我的json?

The solution to this is so easy and simple it will practically make you laugh, but before I even get to it, let me first emphasize that no self-respecting Java developer would ever, and I mean EVER work with JSON without utilizing the Jackson high-performance JSON library. 解决方案是如此简单,简单,几乎会让您发笑,但是在我开始之前,我首先要强调一点,就是没有自尊的Java开发人员,我的意思是说,在不利用Jackson高水平的情况下,永远使用JSON进行工作。性能JSON库。

Jackson is not only a work horse and a defacto JSON library for Java developers, but it also provides a whole suite of API calls that makes JSON integration with Java a piece of cake (you can download Jackson at http://jackson.codehaus.org/ ). Jackson不仅是Java开发人员的工作量和事实上的JSON库,而且还提供了一整套API调用,使JSON与Java的集成变得轻而易举 (您可以从http://jackson.codehaus下载Jackson 。 org / )。

Now for the answer. 现在为答案。 Assuming that you have a UserProfile pojo that looks something like this: 假设您有一个类似于以下内容的UserProfile pojo:

public class UserProfile {

private String email;
// etc...

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

// more getters and setters...
}

...then your Spring MVC method to convert a GET parameter name "profileJson" with JSON value of {"email": "mymail@gmail.com"} would look like this in your controller: ...然后,您的Spring MVC方法将JSON参数为{“ email”:“ mymail@gmail.com”}的GET参数名称“ profileJson”转换为以下代码:

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper; // this is your lifesaver right here

//.. your controller class, blah blah blah

@RequestMapping(value="/register", method = RequestMethod.GET) 
public SessionInfo register(@RequestParam("profileJson") String profileJson) 
throws JsonMappingException, JsonParseException, IOException {

    // now simply convert your JSON string into your UserProfile POJO 
    // using Jackson's ObjectMapper.readValue() method, whose first 
    // parameter your JSON parameter as String, and the second 
    // parameter is the POJO class.

    UserProfile profile = 
            new ObjectMapper().readValue(profileJson, UserProfile.class);

        System.out.println(profile.getEmail());

        // rest of your code goes here.
}

Bam! am! You're done. 你完成了。 I would encourage you to look through the bulk of Jackson API because, as I said, it is a lifesaver. 我鼓励您仔细阅读Jackson的大部分内容,因为正如我所说,这是一个救命稻草。 For example, are you returning JSON from your controller at all? 例如,您是否要从控制器完全返回JSON? If so, all you need to do is include JSON in your lib, and return your POJO and Jackson will AUTOMATICALLY convert it into JSON. 如果是这样,您所需要做的就是在您的库中包含JSON,然后返回您的POJO,Jackson会自动将其转换为JSON。 You can't get much easier than that. 您无法比这容易得多。 Cheers! 干杯! :-) :-)

This could be done with a custom editor, that converts the JSON into a UserProfile object: 这可以通过自定义编辑器完成,该编辑器将JSON转换为UserProfile对象:

public class UserProfileEditor extends PropertyEditorSupport  {

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        ObjectMapper mapper = new ObjectMapper();

        UserProfile value = null;

        try {
            value = new UserProfile();
            JsonNode root = mapper.readTree(text);
            value.setEmail(root.path("email").asText());
        } catch (IOException e) {
            // handle error
        }

        setValue(value);
    }
}

This is for registering the editor in the controller class: 这是为了在控制器类中注册编辑器:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(UserProfile.class, new UserProfileEditor());
}

And this is how to use the editor, to unmarshall the JSONP parameter: 这是使用编辑器解组JSONP参数的方法:

@RequestMapping(value = "/jsonp", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE})
@ResponseBody
SessionInfo register(@RequestParam("profileJson") UserProfile profileJson){
  ...
}

You can create your own Converter and let Spring use it automatically where appropriate: 您可以创建自己的Converter并让Spring在适当的地方自动使用它:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
class JsonToUserProfileConverter implements Converter<String, UserProfile> {

    private final ObjectMapper jsonMapper = new ObjectMapper();

    public UserProfile convert(String source) {
        return jsonMapper.readValue(source, UserProfile.class);
    }
}

As you can see in the following controller method nothing special is needed: 如您在以下控制器方法中看到的,不需要任何特殊的操作:

@GetMapping
@ResponseBody
public SessionInfo register(@RequestParam UserProfile userProfile)  {
  ...
}

Spring picks up the converter automatically if you're using component scanning and annotate the converter class with @Component . 如果您使用组件扫描,Spring会自动选择转换器,并使用@Component注释转换器类。

Learn more about Spring Converter and type conversions in Spring MVC . 了解有关Spring MVC中的 Spring Converter类型转换的更多信息。

This does solve my immediate issue, but I'm still curious as to how you might pass in multiple JSON objects via an AJAX call. 这确实解决了我眼前的问题,但是我仍然对如何通过AJAX调用传递多个JSON对象感到好奇。

The best way to do this is to have a wrapper object that contains the two (or multiple) objects you want to pass. 最好的方法是使包装对象包含要传递的两个(或多个)对象。 You then construct your JSON object as an array of the two objects ie 然后,您将JSON对象构造为两个对象的数组,即

[
  {
    "name" : "object1",
    "prop1" : "foo",
    "prop2" : "bar"
  },
  {
    "name" : "object2",
    "prop1" : "hello",
    "prop2" : "world"
  }
]

Then in your controller method you recieve the request body as a single object and extract the two contained objects. 然后,在控制器方法中,将请求主体作为一个对象接收,并提取两个包含的对象。 ie: 即:

@RequestMapping(value="/handlePost", method = RequestMethod.POST, consumes = {      "application/json" })
public void doPost(@RequestBody WrapperObject wrapperObj) { 
     Object obj1 = wrapperObj.getObj1;
     Object obj2 = wrapperObj.getObj2;

     //Do what you want with the objects...


}

The wrapper object would look something like... 包装对象看起来像...

public class WrapperObject {    
private Object obj1;
private Object obj2;

public Object getObj1() {
    return obj1;
}
public void setObj1(Object obj1) {
    this.obj1 = obj1;
}
public Object getObj2() {
    return obj2;
}
public void setObj2(Object obj2) {
    this.obj2 = obj2;
}   

}

只需在此参数之前添加@RequestBody批注

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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