java 将json字符串转换为不带键的对象

o7jaxewo  于 2022-12-10  发布在  Java
关注(0)|答案(1)|浏览(185)

每个对象都有一个不带键的json字符串,如

[
    {
        "name": "A",
        "number": 1,
        "age": 20
    },
    {
        "name": "B",
        "number": 2,
        "age": 30
    },
    {
        "name": "C",
        "number": 3,
        "age": 40
    }
]

我只需要name和number,所以我有一个如下所示的类,试图将json字符串编码到其中

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@EqualsAndHashCode(callSuper = true)
public class FooResClass extends BaseResModel {

 private static final long serialVersionUID = -6398045272254450504L;

 private List<AData> aDataList;

  @Data
  @JsonIgnoreProperties(ignoreUnknown = true)
  public class AData {
    @JsonProperty("number")
    private Long number;
    @JsonProperty("name")
    private String name;
  }

然后它说

jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of

我做错什么了吗?

iszxjhcz

iszxjhcz1#

TL;DR的名称

您的JSON和POJO不匹配,有几种方法可以解决这个问题:

  • 将JSON解析为List<FooResClass.AData>,然后示例化FooResClass;
  • 定义自定义反串行化器(* 允许重用解析逻辑,如果您选择更改代码,这将是首选方法 *);
  • 更改JSON的结构。

详细信息

首先,如果AData是嵌套的,则它应该是static(否则,示例化将需要封闭类的示例,并且解析将失败)。
第二,JSON表示与AData类对应的JSON对象的Array。也就是说,它不是JSON对象,而是JSON数组,它与List<AData>匹配,但不与包含类FooResClass的示例匹配。
例如,以下解析将成功:

String json = // your json data
ObjectMapper mapper = new ObjectMapper();

List<AData> aData = mapper.readValue(json,  new TypeReference<List<FooResClass.AData>>(){});
FooResClass fooRes = new FooResClass(aDataList); // assuming that all-args constructor was defined

为了使用当前代码获得FooResClass的示例,JSON应该按以下方式构建:

{
   "aDataList":[
      {
         "name":"A",
         "number":1,
         "age":20
      },
      {
         ...
      },
      {
         ...
      }
   ]
}

如果不能更改JSON的结构,则需要定制FooResClass的反序列化。

解串器

为此,您可以通过扩展StdDeserializer并重写其抽象方法deserialize()来定义自定义反串行化程序。
这就是它的实现方式:

public class FooResClassDeserializer extends StdDeserializer<FooResClass> {

    public FooResClassDeserializer() {
        this(null);
    }

    public FooResClassDeserializer(Class<FooResClass> vc) {
        super(vc);
    }

    @Override
    public FooResClass deserialize(JsonParser p,
                                   DeserializationContext ctxt) throws IOException, JacksonException {
        
        ObjectMapper mapper = new ObjectMapper();
        List<FooResClass.AData> aDataList = mapper.readValue(p, new TypeReference<>() {});
        return new FooResClass(aDataList);
    }
}

要指示Jackson在帕辛FooResClass时应使用此Desirializer,您需要使用@JsonDeserialize注解此类,并通过using属性指定Desirializer的类。

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@JsonDeserialize(using = FooResClassDeserializer.class)
public static class FooResClass extends BaseResModel {

    private static final long serialVersionUID = -6398045272254450504L;

    @JsonProperty("aDataList")
    private List<AData> aDataList;

    @Data
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class AData {
        @JsonProperty("number")
        private Long number;
        @JsonProperty("name")
        private String name;
    }
}

通过这个更改,您将能够将当前未更改的JSON解析为FooResClass的示例(* 我通过删除 * extends * 子句测试了这个解决方案,因为您没有提供 * BaseResModelclass)。

相关问题