我有
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
SessionInfo register(UserProfile profileJson){
...
}
我以这种方式传递profileJson:
http://server/url?profileJson={"email":"mymail@gmail.com"}
但我的profileJson对象具有所有空字段。 我该怎么办才能让春天解析我的json?
将JSON传递给查询参数没有意义。您至少需要对其进行URL编码。
我正在编码它。
您将json作为URL参数传递而不是正文(这是默认值)。通常将JSON作为参数传递是没有意义的。使用@RequestParam注释方法参数。但是如前所述,您应该将其作为请求的主体传递,并且可能也作为POST而不是GET请求。
你几乎肯定想在这里使用POST,拥有get的请求主体非常罕见(stackoverflow.com/questions/978061/http-get-with-request-body)
我使用jsonp,它不支持POST。使用@RequestParam注释参数会导致异常,但找不到匹配的编辑器或转换策略
只需将参数作为String并自行转换即可。
亲爱的索蒂里奥斯,这就是我目前的做法,但经过代码审查后,我被要求优雅地做到这一点。
(当回复某人时,请使用@他们的名字。否则,他们不会收到通知。)或者,您可以编写HttpMessageConverter,但如果您想要的内容不是,则使用@RequestBody并没有任何意义在身体里。
这个解决方案非常容易和简单,实际上会让你发笑,但在我开始讨论之前,让我首先强调一点,没有自尊的Java开发人员,我的意思是在没有利用Jackson高的情况下与JSON合作性能JSON库。
Jackson不仅是Java工作者和Java开发人员的事实JSON库,它还提供了一整套API调用,使JSON与Java的集成变得轻而易举(您可以在http://jackson.codehaus下载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方法转换一个GET参数名称"profileJson",其JSON值为{"email":"mymail@gmail.com"}在你的控制器中看起来像这样:
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.
}
巴姆!你完成了。我鼓励你仔细研究一下Jackson API,因为正如我所说,它是一个救星。例如,您是否从控制器返回JSON?如果是这样,您需要做的就是在您的lib中包含JSON,并返回您的POJO,Jackson将自动将其转换为JSON。你不可能比这更容易。干杯! :-)
我希望这里有@RequestParameter注释的一些参数。
为每个请求ObjectMapper创建它并不是一个好习惯。控制器应该有字段ObjectMapper。
实际上,这是不正确的。首先,我假设"字段"表示控制器类的实例变量。其次,我的例子的目的是演示ObjectMapper的使用,而不是提供最佳实践并深入研究对象实例化的更精细的架构细节。第三,最重要的是,将ObjectMapper作为控制器的实例变量只是简单的坏习惯,因为Spring控制器默认是单例。正确的方法是遵循标准MVC模式并自动装配包含ObjectMapper的服务类。
@TheSaint我只是好奇,为什么单身控制器有这样的字段的坏习惯?
@grape_mao,根据其作者的说法,ObjectMapper在Jackson 2.x中不被认为是完全线程安全的:stackoverflow.com/a/3909846/1199132
创建Converter并让Spring MVC自动使用它会更优雅(也可能更高效)。请参阅我的答案以获取示例。
这可以使用自定义编辑器完成,该编辑器将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){
...
}
这看起来很通用,我想知道是否真的有必要为我希望以这种方式解析的每个类编写和注册自定义编辑器。
将此添加到调度程序servlet xml为我工作mvc:message-converters > mvc:annotation-driven>
使用Converter可以更简单。请参阅我的答案以获取示例。
您可以创建自己的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 {
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 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.
执行此操作的最佳方法是使用包含要传递的两个(或多个)对象的包装器对象。然后,您将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;
}
}
只需在此参数之前添加@RequestBody注释即可
这不起作用。我得到HTTP 415:服务器拒绝了这个请求,因为请求实体的格式不受所请求方法所请求资源的支持。
默认情况下,@RequestBody查看请求的正文。 OPs内容是作为查询字符串的一部分发送的请求参数。
这项工作对我来说。我用@RestController