Spring MVC控制器中的JSON参数

时间:2014-02-05 12:49:15

标签: java json spring spring-mvc

我有

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

我以这种方式传递profileJson:

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

但我的profileJson对象包含所有空字段。我应该怎么做才能让我的json解析春天?

5 个答案:

答案 0 :(得分:30)

解决这个问题非常容易和简单,实际上会让你发笑,但在我开始讨论之前,让我首先强调一点,没有自尊的Java开发人员,我的意思是在没有利用的情况下使用JSON杰克逊的高性能JSON库。

杰克逊不仅是Java工作者和Java开发人员的事实JSON库,它还提供了一整套API调用,使JSON与Java的集成变得轻而易举(您可以在http://jackson.codehaus.org/下载Jackson )。

现在回答。假设您有一个类似于这样的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...
}

...然后你的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!你完成了。我鼓励你仔细研究一下Jackson API,因为正如我所说,它是一个救星。例如,您是否从控制器返回JSON?如果是这样,您需要做的就是在您的lib中包含JSON,并返回您的POJO,Jackson将自动将其转换为JSON。你不可能比这更容易。干杯! : - )

答案 1 :(得分:25)

这可以通过自定义编辑器完成,该编辑器将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);
    }
}

这是用于在控制器类中注册编辑器:

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

这是如何使用编辑器来解组JSONP参数:

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

答案 2 :(得分:3)

您可以创建自己的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);
    }
}

正如您在以下控制器方法中所看到的,没有什么特别需要:

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

如果您正在使用组件扫描并使用@Component注释转换器类,则Spring会自动选择转换器。

详细了解Spring Convertertype conversions in Spring MVC

答案 3 :(得分:1)

  

这确实解决了我的问题,但我仍然对如何通过AJAX调用传递多个JSON对象感到好奇。

执行此操作的最佳方法是使用包含要传递的两个(或多个)对象的包装器对象。然后,将JSON对象构造为两个对象的数组,即

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

然后在您的控制器方法中,您将请求正文作为单个对象接收并提取包含的两个对象。即:

@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...


}

包装器对象看起来像......

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;
}   

}

答案 4 :(得分:-5)

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