jaxrs找不到我的joda.money类型的自定义(de)序列化程序

我已经为joda.money.Money类型编写了我的自定义(de)序列化joda.money.Money 。 我用Object Mapper注册它们。 但是当我部署我的war文件时,它说找不到joda.money.Money类型的序列化器。

 import org.joda.money.Money; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; public class MoneyDeserializer extends StdDeserializer { private static final long serialVersionUID = 1L; public MoneyDeserializer() { super(Money.class); } @Override public Money deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException { ... } } 

在ObjectMapper中注册;

 import org.codehaus.jackson.jaxrs.JacksonJsonProvider; import org.joda.money.Money; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.joda.JodaModule; import xx.serializers.MoneyDeserializer; import xx.serializers.MoneySerializer @Provider public class JsonProvider extends JacksonJsonProvider { public JsonProvider() { ObjectMapper mapper = new ObjectMapper(); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // Register  (de)serializers SimpleModule tstmodule = new SimpleModule("MyModule", new Version(1, 0, 0, null)); tstmodule.addDeserializer(Money.class, new MoneyDeserializer()); tstmodule.addSerializer(Money.class, new MoneySerializer()); mapper.registerModule(tstmodule); mapper.registerModule(new JodaModule()); } } 2:24:00,860 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 151) MSC000001: Failed to start service jboss.undertow.deployment.default-server.default-host./api: org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./api: java.lang.RuntimeException: Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam("sale") on public javax.ws.rs.core.Response com.xx.getItems(java.lang.Integer,java.lang.Integer,java.lang.String,java.lang.Long,org.joda.money.Money,java.lang.String,java.lang.Long,java.time.LocalDateTime,java.time.LocalDateTime,java.time.LocalDateTime,java.lang.Long,java.lang.Long,java.lang.Long,java.lang.Long,java.lang.String) for basetype: org.joda.money.Money at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:85) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) at org.jboss.threads.JBossThread.run(JBossThread.java:320) Caused by: java.lang.RuntimeException: Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam("sale") on public javax.ws.rs.core.Response xx.getItems(java.lang.Integer,java.lang.Integer,java.lang.String,java.lang.Long,org.joda.money.Money,java.lang.String,java.lang.Long,java.time.LocalDateTime,java.time.LocalDateTime,java.time.LocalDateTime,java.lang.Long,java.lang.Long,java.lang.Long,java.lang.Long,java.lang.String) for basetype: org.joda.money.Money at org.jboss.resteasy.core.StringParameterInjector.initialize(StringParameterInjector.java:218) 

我看到你在JsonProvider构造函数中创建了ObjectMapper但从未使用它。 你可能应该使用setMapper(mapper); 在构造函数最后的JsonProvider上。

但我不认为这会解决你的问题。 我认为问题是jaxrs只理解简单的数据类型,如果你想使用自定义类,你必须为基于String的@*Param实现某种String编组操作

从你的堆栈跟踪我看到你使用jboss ,所以也许这可以帮助? https://docs.jboss.org/resteasy/docs/3.0.12.Final/userguide/html/StringConverter.html

如果您有一个类,其中valueOf()或此字符串构造函数不存在或不适合HTTP请求,该怎么办? JAX-RS 2.0有javax.ws.rs.ext.ParamConverterProvider来帮助解决这种情况。 有关更多详细信息,请参阅javadoc。

https://docs.oracle.com/javaee/7/api/javax/ws/rs/ext/ParamConverterProvider.html

这样的事情应该可行:

 @Provider public class MoneyConverterProvider implements ParamConverterProvider { private final MoneyConverter converter = new MoneyConverter(); @Override public  ParamConverter getConverter(Class rawType, Type genericType, Annotation[] annotations) { if (!rawType.equals(Money.class)) return null; return (ParamConverter) converter; } public class MoneyConverter implements ParamConverter { public Money fromString(String value) { if (value == null ||value.isEmpty()) return null; // change this for production return Money.of(CurrencyUnit.EUR, Double.parseDouble(value)); } public String toString(Money value) { if (value == null) return ""; return value.getAmount().toString(); // change this for production } } }