如何配置Jackson的ObjectMapper处理空输入流并返回null?
解决Jackson读取空输入流返回null的问题
你用的DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT配置只对**空JSON数组(如[])**生效,但当前场景是输入流完全没有内容,连空数组的字符都不存在,所以这个配置起不到作用。
下面提供两种可行的解决方式:
方法一:捕获EOF相关异常返回null
直接捕获Jackson抛出的MismatchedInputException,判断异常根源是EOF(流结束)时返回null,其他异常正常抛出:
try { return objectMapper.readValue(val, new TypeReference<Object>() {}); } catch (MismatchedInputException e) { if (e.getCause() instanceof EOFException) { return null; } throw e; } catch (IOException e) { // 根据业务需求处理其他IO异常,比如抛出运行时异常或返回null throw new RuntimeException("读取输入流失败", e); }
方法二:包装输入流模拟null值
自定义一个输入流装饰器,当原流为空时,自动返回JSON的null字符序列,让Jackson解析成null:
import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; public class EmptyStreamAsNullInputStream extends FilterInputStream { private boolean hasStarted; private int nullByteIndex; private final byte[] nullBytes = "null".getBytes(StandardCharsets.UTF_8); public EmptyStreamAsNullInputStream(InputStream in) { super(in); } @Override public int read() throws IOException { if (!hasStarted) { hasStarted = true; int firstByte = super.read(); if (firstByte == -1) { // 原流为空,返回"null"的字节 if (nullByteIndex < nullBytes.length) { return nullBytes[nullByteIndex++]; } return -1; } return firstByte; } if (nullByteIndex < nullBytes.length) { return nullBytes[nullByteIndex++]; } return super.read(); } @Override public int read(byte[] b, int off, int len) throws IOException { if (!hasStarted) { int firstRead = super.read(b, off, len); if (firstRead == -1) { // 原流为空,写入"null"字节 int bytesToWrite = Math.min(len, nullBytes.length); System.arraycopy(nullBytes, 0, b, off, bytesToWrite); nullByteIndex = bytesToWrite; hasStarted = true; return bytesToWrite; } hasStarted = true; return firstRead; } if (nullByteIndex < nullBytes.length) { int bytesToWrite = Math.min(len, nullBytes.length - nullByteIndex); System.arraycopy(nullBytes, nullByteIndex, b, off, bytesToWrite); nullByteIndex += bytesToWrite; return bytesToWrite; } return super.read(b, off, len); } }
使用时将原流包装后传入:
Object result = objectMapper.readValue(new EmptyStreamAsNullInputStream(val), new TypeReference<Object>() {});
两种方法对比:方法一代码简洁、易维护,适合大多数场景;方法二无需修改readValue的调用逻辑,对原有代码侵入性低,但需要维护自定义流的逻辑。
内容的提问来源于stack exchange,提问作者lovrodoe
相关产品推荐
相关产品推荐

