GeXiangDong

精通Java、SQL、Spring的拼写,擅长Linux、Windows的开关机

0%

org.springframework.web.HttpMediaTypeNotSupportedException: Content type application/json

在使用Springboot 时遇到错误,服务端日志如下:

1
WARN  o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported]

RestController里

1
2
3
4
@RequestMapping(
value = "/xxxxxs",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)

看上去这个错误原因很简单,客户端传递的 Content-Type 没有在服务器端支持。

检查发现,客户端和服务器端都是正确,而且同一个controller里有的POST是好的,不出问题,有的出问题。

网上搜到的办法也都试过,pom中依赖也改过….

后来把日志级别 org.springframeword 改为 TRACE,然后发现日志中有这么一段(有堆栈,很容发现)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
12:49:56.112 [http-nio-8050-exec-3] DEBUG o.s.h.c.j.MappingJackson2HttpMessageConverter - Failed to evaluate Jackson deserialization for type [[simple type, class cn.devmgr.mall.product.pojo.Category]]
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot find a (Map) Key deserializer for type [simple type, class cn.devmgr.mall.product.pojo.ProductPriceKey]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1589)
at com.fasterxml.jackson.databind.deser.DeserializerCache._handleUnknownKeyDeserializer(DeserializerCache.java:599)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findKeyDeserializer(DeserializerCache.java:168)
at com.fasterxml.jackson.databind.DeserializationContext.findKeyDeserializer(DeserializationContext.java:499)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.createContextual(MapDeserializer.java:248)
at com.fasterxml.jackson.databind.DeserializationContext.handlePrimaryContextualization(DeserializationContext.java:650)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:484)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:443)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:183)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:27)
at com.fasterxml.jackson.databind.DeserializationContext.handlePrimaryContextualization(DeserializationContext.java:650)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:484)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.hasValueDeserializerFor(DeserializerCache.java:191)
at com.fasterxml.jackson.databind.DeserializationContext.hasValueDeserializerFor(DeserializationContext.java:421)

现在原因就很明显了,ProductPriceKey作为map的key导致的。这个属性我本不需要客户端传递,于是在属性增加了只读。

1
2
3
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Map<ProductPriceKey, ProductPrice> salePrices;

Java类和JSON字符串互转,map需要key是string,这个很容易理解,不是string的没法转。(java->json部分在这个类内之前有处理;反过来没处理)

这样就解决了。

这个问题本应该更容易发现,只是spring/fasterxml内把这个错误的日志级别用了DEBUG,不太容易被发现。