Spring - 将 pojo 转换为 JSON 时出现问题(未发现转换器错误)
Spring - Problem converting a pojo to a JSON (No converter found error)
spring 4.3.3
我正在尝试将 Pojo 转换为 JSON,将控制器标记为
@RestController,问题是有些元素的首字母小写而不是大写,
Ex:
"Id": 1, //This is ok
"customerId": "1234", //Instead of CustomerId, this has customerId
...
控制器
@RestController
...
public class CustomerController{
...
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public CustomerResponse postCustomerRequest(final HttpServletRequest request) {
我希望它是大写的。 pojo 基本上是从 xsd 生成 class 的 xjc,它包含
@XmlElement(name = "Id")
protected int id;
@XmlElement(name = "CustomerId")
protected String customerId;
...
public int getId() {
return id;
}
public void setId(int value) {
this.id = value;
}
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String value) {
this.customerId = value;
}
这为每个属性关联了 setter、getter。在控制器中,我也将不区分大小写的 ObjectMapper 设置为 true,
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
我也尝试过,将控制器标记为@Controller 而不是@RestController,在方法之前提供@ResponseBody,
控制器
@Controller
...
public class CustomerController {
...
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@ResponseBody
public String postCustomerRequest(HttpServletRequest request) {
...
//Used PropertyNamingStrategy with the ObjectMapper, converted the first character to an upper case,
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
...
CustomerResponse response=createCustomer(document,objectFactory);
mapperObj.setPropertyNamingStrategy(new CustomerJsonNameStrategy());
String jsonOutput = mapperObj.writeValueAsString(response);
return jsonOutput;
如果我在 Eclipse 中调试期间看到 jsonOutput 的值,它会以正确的大小写输出 json 元素,但对其余客户端的响应是
{"errors": [{
"message": "No converter found for return value of type: class java.lang.String",
"type": "IllegalArgumentError"
}]}
看起来 jackson 序列化程序正在干扰响应并抛出上述错误。
解决这个问题的方法是什么?
Spring 使用 Jackson 将 POJO 转换为 json。默认情况下,杰克逊使字段名称的第一个字母变小。如果您想要自定义名称,请添加以下杰克逊注释。
@JsonProperty("CustomerId")
private String customerId;
@Consumes 在这种情况下对你帮助不大。它应该用于指定输入的格式。查看这篇文章:
http://www.javainterviewpoint.com/jax-rs-rest-consumes-example/
如果您在调试期间可以看到 jsonOutput,则您的问题可能与您的客户端期望输出的方式有关:您的客户端可能期望 JSON 而不是 String 对象。
解决方案:return CustomerResponse 而不是 String。
@RestController
...
public class CustomerController {
...
public CustomerResponse postCustomerRequest(final HttpServletRequest request)
{
如果您想更改默认命名,CustomerResponse 应该使用 @JsonProperty 注释字段。
@JsonProperty(name = "Id")
protected int id;
@JsonProperty(name = "CustomerId")
protected String customerId;
我会使用您的自定义 属性 命名策略配置 MappingJackson2HttpMessageConverter
,恕我直言,与在每个控制器方法中序列化为 json 相比,这是更清洁的解决方案
<mvc:annotation-driven>
<mvc:message-converters>
...
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="objectMapper"/>
</bean>
...
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="propertyNamingStrategy" ref="customNamingStrategy" />
</bean
或者,如果您确实想要或需要控制响应主体,请确保 StringHttpMessageConverter
在 spring MVC 配置中注册为转换器
<mvc:annotation-driven>
<mvc:message-converters>
...
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
...
</mvc:message-converters>
</mvc:annotation-driven>
我通过移动到没有 jackson 设置的扩展来让它工作。 PS:这是在 SAP Hybris 和
它包含多个 extensions/projects.
我用@Controller 标记了Controller,添加了@Produces({MediaType.APPLICATION_JSON}),移除了@ResponseBody,将方法return类型设置为ResponseEntity,
使用 PropertyNamingStrategy 将首字母转换为大写。
public ResponseEntity<String> postCustomerRequest(final HttpServletRequest request) {
...
final org.codehaus.jackson.map.ObjectMapper mapperObj = new org.codehaus.jackson.map.ObjectMapper();
CustomerResponse response=createCustomer(document,objectFactory);
mapperObj.setPropertyNamingStrategy(new CustomerJsonNameStrategy());
final HttpHeaders httpHeaders= new HttpHeaders();
httpHeaders.setContentType(org.springframework.http.MediaType.APPLICATION_JSON);
return new ResponseEntity<String>(mapperObj.writeValueAsString(response), httpHeaders, HttpStatus.OK);
}
spring 4.3.3
我正在尝试将 Pojo 转换为 JSON,将控制器标记为
@RestController,问题是有些元素的首字母小写而不是大写,
Ex:
"Id": 1, //This is ok
"customerId": "1234", //Instead of CustomerId, this has customerId
...
控制器
@RestController
...
public class CustomerController{
...
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public CustomerResponse postCustomerRequest(final HttpServletRequest request) {
我希望它是大写的。 pojo 基本上是从 xsd 生成 class 的 xjc,它包含
@XmlElement(name = "Id")
protected int id;
@XmlElement(name = "CustomerId")
protected String customerId;
...
public int getId() {
return id;
}
public void setId(int value) {
this.id = value;
}
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String value) {
this.customerId = value;
}
这为每个属性关联了 setter、getter。在控制器中,我也将不区分大小写的 ObjectMapper 设置为 true,
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
我也尝试过,将控制器标记为@Controller 而不是@RestController,在方法之前提供@ResponseBody,
控制器
@Controller
...
public class CustomerController {
...
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@ResponseBody
public String postCustomerRequest(HttpServletRequest request) {
...
//Used PropertyNamingStrategy with the ObjectMapper, converted the first character to an upper case,
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
...
CustomerResponse response=createCustomer(document,objectFactory);
mapperObj.setPropertyNamingStrategy(new CustomerJsonNameStrategy());
String jsonOutput = mapperObj.writeValueAsString(response);
return jsonOutput;
如果我在 Eclipse 中调试期间看到 jsonOutput 的值,它会以正确的大小写输出 json 元素,但对其余客户端的响应是
{"errors": [{
"message": "No converter found for return value of type: class java.lang.String",
"type": "IllegalArgumentError"
}]}
看起来 jackson 序列化程序正在干扰响应并抛出上述错误。
解决这个问题的方法是什么?
Spring 使用 Jackson 将 POJO 转换为 json。默认情况下,杰克逊使字段名称的第一个字母变小。如果您想要自定义名称,请添加以下杰克逊注释。
@JsonProperty("CustomerId")
private String customerId;
@Consumes 在这种情况下对你帮助不大。它应该用于指定输入的格式。查看这篇文章: http://www.javainterviewpoint.com/jax-rs-rest-consumes-example/
如果您在调试期间可以看到 jsonOutput,则您的问题可能与您的客户端期望输出的方式有关:您的客户端可能期望 JSON 而不是 String 对象。 解决方案:return CustomerResponse 而不是 String。
@RestController
...
public class CustomerController {
...
public CustomerResponse postCustomerRequest(final HttpServletRequest request)
{
如果您想更改默认命名,CustomerResponse 应该使用 @JsonProperty 注释字段。
@JsonProperty(name = "Id")
protected int id;
@JsonProperty(name = "CustomerId")
protected String customerId;
我会使用您的自定义 属性 命名策略配置 MappingJackson2HttpMessageConverter
,恕我直言,与在每个控制器方法中序列化为 json 相比,这是更清洁的解决方案
<mvc:annotation-driven>
<mvc:message-converters>
...
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="objectMapper"/>
</bean>
...
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="propertyNamingStrategy" ref="customNamingStrategy" />
</bean
或者,如果您确实想要或需要控制响应主体,请确保 StringHttpMessageConverter
在 spring MVC 配置中注册为转换器
<mvc:annotation-driven>
<mvc:message-converters>
...
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
...
</mvc:message-converters>
</mvc:annotation-driven>
我通过移动到没有 jackson 设置的扩展来让它工作。 PS:这是在 SAP Hybris 和 它包含多个 extensions/projects.
我用@Controller 标记了Controller,添加了@Produces({MediaType.APPLICATION_JSON}),移除了@ResponseBody,将方法return类型设置为ResponseEntity, 使用 PropertyNamingStrategy 将首字母转换为大写。
public ResponseEntity<String> postCustomerRequest(final HttpServletRequest request) {
...
final org.codehaus.jackson.map.ObjectMapper mapperObj = new org.codehaus.jackson.map.ObjectMapper();
CustomerResponse response=createCustomer(document,objectFactory);
mapperObj.setPropertyNamingStrategy(new CustomerJsonNameStrategy());
final HttpHeaders httpHeaders= new HttpHeaders();
httpHeaders.setContentType(org.springframework.http.MediaType.APPLICATION_JSON);
return new ResponseEntity<String>(mapperObj.writeValueAsString(response), httpHeaders, HttpStatus.OK);
}