Jackson反序列化报错:无法将Object转为java.lang.String的解决方法求助
解决Jackson反序列化类型不匹配的问题
问题根源
你判断的完全正确:ConfigurationProperties类中propertiesJson字段定义为String类型,但输入JSON中对应的是嵌套JSON对象,Jackson尝试将对象解析为字符串时,必然抛出MismatchedInputException类型不匹配异常。
解决方案
根据是否允许修改类结构,提供两种可行方案:
方案1:修改ConfigurationProperties类的字段类型(推荐)
如果可以调整类结构,直接将propertiesJson的类型从String改为JsonNode或Object,让Jackson直接解析嵌套对象:
修改后的ConfigurationProperties类
public class ConfigurationProperties { private String propertiesClass; // 替换为JsonNode,保留JSON结构信息 private JsonNode propertiesJson; }
后续解析为具体类型
反序列化整个Configurations后,再根据propertiesClass指定的类名,将JsonNode转换为对应的Java对象:
ObjectMapper objectMapper = new ObjectMapper(); // 开启字符串转数值特性,处理latency、permittedTransactionsPerSecond的字符串格式数值 objectMapper.enable(DeserializationFeature.ACCEPT_STRING_AS_NUMERIC_VALUE); // 反序列化整体配置 Configurations configs = objectMapper.readValue(input, Configurations.class); // 获取第一个配置项的属性节点 ConfigurationProperties configProps = configs.getConfigurations().get(0).getConfigurationProperties(); JsonNode propertiesNode = configProps.getPropertiesJson(); // 根据propertiesClass反射获取目标类 Class<?> targetClass = Class.forName(configProps.getPropertiesClass()); // 将JsonNode转换为具体对象 Object properties = objectMapper.treeToValue(propertiesNode, targetClass);
方案2:自定义反序列化器,将JSON对象转为字符串(不修改类结构)
如果必须保留propertiesJson为String类型,需要自定义反序列化器,将输入的JSON对象序列化为JSON字符串:
1. 编写自定义反序列化器
public class JsonObjectToStringDeserializer extends JsonDeserializer<String> { @Override public String deserialize(JsonParser parser, DeserializationContext context) throws IOException { // 将JSON节点转换为JSON字符串 JsonNode node = parser.getCodec().readTree(parser); return parser.getCodec().writeValueAsString(node); } }
2. 给propertiesJson字段添加注解
public class ConfigurationProperties { private String propertiesClass; // 指定使用自定义反序列化器 @JsonDeserialize(using = JsonObjectToStringDeserializer.class) private String propertiesJson; }
3. 后续解析具体类型
反序列化完成后,再将JSON字符串转换为目标类对象:
ObjectMapper objectMapper = new ObjectMapper(); objectMapper.enable(DeserializationFeature.ACCEPT_STRING_AS_NUMERIC_VALUE); Configurations configs = objectMapper.readValue(input, Configurations.class); String propsJsonStr = configs.getConfigurations().get(0).getConfigurationProperties().getPropertiesJson(); // 转换为具体类 SchoolProperties schoolProps = objectMapper.readValue(propsJsonStr, SchoolProperties.class);
额外处理:possibleExceptions字段的反序列化
输入JSON中possibleExceptions是类名字符串数组,而SchoolProperties中是Class<? extends Throwable>[]类型,需要额外自定义反序列化器:
编写Class数组反序列化器
public class ThrowableClassArrayDeserializer extends JsonDeserializer<Class<? extends Throwable>[]> { @Override public Class<? extends Throwable>[] deserialize(JsonParser parser, DeserializationContext context) throws IOException { JsonNode node = parser.getCodec().readTree(parser); List<Class<? extends Throwable>> classList = new ArrayList<>(); for (JsonNode itemNode : node) { try { Class<?> clazz = Class.forName(itemNode.asText()); // 校验是否为Throwable子类 if (Throwable.class.isAssignableFrom(clazz)) { classList.add((Class<? extends Throwable>) clazz); } else { throw new IOException("Class " + itemNode.asText() + " is not a subclass of Throwable"); } } catch (ClassNotFoundException e) { throw new IOException("Failed to load class: " + itemNode.asText(), e); } } return classList.toArray(new Class[0]); } }
给possibleExceptions字段添加注解
public class SchoolProperties { @JsonProperty("serviceName") String serviceName; @JsonProperty("operationName") String operationName; @JsonProperty("latency") Long latency; @JsonProperty("permittedTransactionsPerSecond") int permittedTransactionsPerSecond; @JsonDeserialize(using = ThrowableClassArrayDeserializer.class) Class<? extends Throwable>[] possibleExceptions; }
内容的提问来源于stack exchange,提问作者Shivanshu
相关产品推荐
相关产品推荐

