Spring测试中不修改ObjectMapper配置,如何将响应Integer转为Long?
解决ObjectMapper反序列化Long为Integer后的类型转换问题
这问题我之前踩过坑!ObjectMapper默认会把能塞进Integer的数值自动转成Integer类型,导致你后续强转Long时直接炸ClassCastException,不想改全局映射器配置的话,给你几个直接转换的靠谱方案:
方案1:指定精确的反序列化类型(最推荐)
根本不用先转成无泛型的Set再手动转换,直接告诉ObjectMapper你要的是Set<Long>类型,用TypeReference来明确泛型:
Set<Long> responseBody = objectMapper.readValue( result.getContentAsByteArray(), new TypeReference<Set<Long>>() {} ); // 直接就能和otherSet比较,不用后续map转换了 assertThat(responseBody.equals(otherSet), is(true));
这样ObjectMapper会直接把JSON数组里的数值转成Long,从根源上避免类型不匹配的问题。
方案2:安全的类型判断转换
如果因为某些原因必须先读成Set<?>,那转换的时候别直接强转,先判断元素类型再处理:
Set<?> rawResponseBody = objectMapper.readValue(result.getContentAsByteArray(), Set.class); Set<Long> responseBody = rawResponseBody.stream() .map(number -> { if (number instanceof Integer) { return ((Integer) number).longValue(); } else if (number instanceof Long) { return (Long) number; } // 可以根据需求处理其他数字类型,比如BigInteger,或者抛异常提示 throw new IllegalArgumentException("不支持的数字类型: " + number.getClass().getName()); }) .collect(Collectors.toSet()); assertThat(responseBody.equals(otherSet), is(true));
这种方式能兼容Integer和Long两种类型的元素,不会出现强转异常。
方案3:通用的字符串转Long(简单粗暴)
不管元素是Integer还是Long,先转成字符串再转成Long,适合大多数场景:
Set<?> rawResponseBody = objectMapper.readValue(result.getContentAsByteArray(), Set.class); Set<Long> responseBody = rawResponseBody.stream() .map(number -> Long.valueOf(number.toString())) .collect(Collectors.toSet()); assertThat(responseBody.equals(otherSet), is(true));
这个方法不用判断类型,只要元素是数字类型(能正确转成字符串的数字)都能处理,缺点是如果有非数字类型的元素会报错,不过你的场景里应该都是数值,所以没问题。
内容的提问来源于stack exchange,提问作者JeyJ
相关产品推荐
相关产品推荐

