从RestyGwt发布dto时,Spring-MVC缺少@Class信息

时间:2014-11-07 14:30:30

标签: spring-mvc polymorphism jackson resty-gwt

给出一个Spring MVC控制器:

@RequestMapping(method = RequestMethod.POST consumes = RestApiConstants.JSON, produces = RestApiConstants.JSON)
@ResponseBody
public CustomerDto post(@RequestBody final CustomerDto dto) {
  // save it
}

将dto发布到此控制器时,Jackson映射器缺少@class属性:

 2014-11-07 14:20:55 ERROR ... Probably Jackson Mapper has failed.
 org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unexpected token (END_OBJECT), expected FIELD_NAME: missing property '@class' that is to contain type id  (for class com.our.package.CustomerDto)
  at [Source: java.io.PushbackInputStream@66be55c7; line: 1, column: 988]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (END_OBJECT), expected FIELD_NAME: missing property '@class' that is to contain type id  (for class com.our.package.CustomerDto)
  at [Source: java.io.PushbackInputStream@66be55c7; line: 1, column: 988]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:208)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:200)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:138)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:181)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:104)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77)
    ...
 Caused by: com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (END_OBJECT), expected FIELD_NAME: missing property '@class' that is to contain type id  (for class com.our.package.CustomerDto)
  at [Source: java.io.PushbackInputStream@66be55c7; line: 1, column: 988]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
    at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:784)
     ...

CustomerDto被定义为抽象超类PartnerDto的特定子类型:

@JsonSubTypes({
    @Type(Customer.class),
    @Type(Supplier.class)
})
@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY, property = "@class")
public abstract class PartnerDto {
  // ...
}

public class CustomerDto extends PartnerDto {
  // ...
}

RestyGwt发布此CustomerDto:

{   
  "name": "Testname",
  "age": 50,
  ...
}

但是Spring希望如此:

{
  "@class": "com.our.package.CustomerDto",
  "name": "Testname",
  "age": 50,
  ...
}

发生此问题因为我们将Spring和RestyGwt移动到使用Jackson 2映射器(Spring 4.1.1.RELEASE,RestyGWT 2.0-SNAPSHOT,Jackson 2.3.2)。它适用于旧版本(Spring 4.0.7.RELEASE,RestyGWT 1.4,Jackson 1.9.13)。

我该怎么处理?

1 个答案:

答案 0 :(得分:0)

我已经通过失败的单元测试为resty gwt创建了拉取请求。

https://github.com/resty-gwt/resty-gwt/pull/212

为具体实现而不是公共超类型创建JsonEncoder时会出现问题。