调用cxf-rest服务时float被强转为int问题
最近使用cxf-rest开发一个rest接口(由于是老系统,所以使用技术比较旧),在对接口进行测试的时候,有如下用例:
Json字段类型为float,Java Object字段类型为Integer,预期返回 NumberFormatException 错误。
实际执行过程中发现并未抛错,而是将float强转为int。
经查服务端使用的是codehaus.jackson进行的转换,经过代码追踪发现在将Json转换为Java Object时,如果Json字段值为float,会将其强转为int。
具体代码如下:
org.codehaus.jackson.map.deser.std.StdDeserializer#_parseInteger
protected final Integer _parseInteger(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
return Integer.valueOf(jp.getIntValue());
}
if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse
String text = jp.getText().trim();
try {
int len = text.length();
if (len > 9) {
long l = Long.parseLong(text);
if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
throw ctxt.weirdStringException(_valueClass,
"Overflow: numeric value ("+text+") out of range of Integer ("+Integer.MIN_VALUE+" - "+Integer.MAX_VALUE+")");
}
return Integer.valueOf((int) l);
}
if (len == 0) {
return (Integer) getEmptyValue();
}
return Integer.valueOf(NumberInput.parseInt(text));
} catch (IllegalArgumentException iae) {
throw ctxt.weirdStringException(_valueClass, "not a valid Integer value");
}
}
if (t == JsonToken.VALUE_NULL) {
return (Integer) getNullValue();
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
如果希望改变这种转换逻辑,可以重新注册下IntegerDeserializer。参考实现如下:
@Test
public void test() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule("integer", Version.unknownVersion()).addDeserializer(Integer.class, new JsonDeserializer<Integer>() {
@Override
public Integer deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NUMBER_INT) { // coercing should work too
return Integer.valueOf(jp.getIntValue());
}
if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse
String text = jp.getText().trim();
try {
int len = text.length();
if (len > 9) {
long l = Long.parseLong(text);
if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
throw ctxt.weirdStringException(Integer.class,
"Overflow: numeric value (" + text + ") out of range of Integer (" + Integer.MIN_VALUE + " - " + Integer.MAX_VALUE + ")");
}
return Integer.valueOf((int) l);
}
if (len == 0) {
return (Integer) getEmptyValue();
}
return Integer.valueOf(NumberInput.parseInt(text));
} catch (IllegalArgumentException iae) {
throw ctxt.weirdStringException(Integer.class, "not a valid Integer value");
}
}
if (t == JsonToken.VALUE_NULL) {
return (Integer) getNullValue();
}
// Otherwise, no can do:
throw ctxt.mappingException(Integer.class, t);
}
}));
}
或者在Json中使用设置字段值为String类型。