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

}