如何使用 Jackson 从对象反序列化为字符串或布尔值列表?

问题描述 投票:0回答:1

我之前使用 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();
    }
}
java json jackson java-11 jackson-databind
1个回答
0
投票

请设置 @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;

    }

}
© www.soinside.com 2019 - 2024. All rights reserved.