我之前使用 jackson-databind 2.8.11.3 + Java 8 反序列化 ApiRequest 类,该类在 API 调用中用作请求正文。一直运行良好,并且能够生成 JSON 字符串。
在对象参数中,可以添加字符串列表或布尔值。
JSON 示例:
{
"fields":[
{
"key": "colors",
"values": ["blue","red"]
},
{
"key": "metal",
"values": true
}
]
}
当我升级到使用 jackson-databind 2.13.2.2 + Java 11 并运行单元测试来生成 JSON 字符串时,我遇到了一个问题,其中 JSON 定义错误
com.fasterxml.jackson.databind.exc.InvalidDefinitionException:不能 构造“com...”的实例(没有创建者,如默认构造函数, 存在):无法从对象值反序列化(无委托或 基于属性的创建者)位于[来源:(文件)..(通过参考 链:com...ApiRequest["fields"])
在 com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
在 com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1904)
下面是该类的一个片段,我已提取并重命名:
@Data
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiRequest {
private List<Fields> fields;
@Data
@Builder
public static class Fields {
private String key;
private Object values;
}
}
在阅读了其他人在网上发布的其他一些问题后,我尝试使用 JsonDeserializer 来解决该问题,但我没有成功解决这个问题。
任何建议/意见将不胜感激..
@Data
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiRequest {
private List<Fields> fields;
@Data
@Builder
@JsonDeserialize(using = FieldDeserializer.class) <-- added this
public static class Fields {
private String key;
private Object values;
}
}
public class FieldDeserializer extends JsonDeserializer<ApiRequest.Fields> {
@Override
public ApiRequest.Fields deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
String key = node.get("key");
JsonNode valuesNode = node.get("values");
Object values = null;
if (valuesNode.isArray()) {
List<String> listValues = new ArrayList<>();
valuesNode.forEach(elementNode -> listValues.add(elementNode.asText()));
values = listValues;
} else if (valuesNode.isBoolean()) {
values = valuesNode.asBoolean();
}
return new ApiRequest.Fields.builder().key(key).values(values).build();
}
}
请设置 @Jacksonized 以及 @Builder
@Data
@Builder
@Jacksonized
public class ApiRequest {
private List<Field> fields;
@Data
@Builder
@Jacksonized
public static class Field {
private String key;
private Object values;
}
}