JSON转Java对象 - 未被识别的字段,未标记为可忽略

9
我正在尝试将以下JSON转换为Java对象。
{
  "Data":[
    {
      "AccountId":"2009852923",
      "Currency":"EUR",
      "Nickname":"SA 01",
      "Account":{
        "SchemeName":"BBAN",
        "Name":"SA 01",
        "Identification":"2009852923"
      },
      "Servicer":{
        "SchemeName":"BICFI",
        "Identification":"FNBSZAJJ"
      }
    },
    {
      "AccountId":"1028232942",
      "Currency":"EUR",
      "Nickname":"FNBCREDIT",
      "Account":{
        "SchemeName":"BBAN",
        "Name":"FNBCREDIT",
        "Identification":"1028232942"
      },
      "Servicer":{
        "SchemeName":"BICFI",
        "Identification":"FNBSZAJJ"
      }
    }
  ],
  "Links":{
    "self":"http://localhost:3000/api/open-banking/accounts/1009427721/transactions"
  },
  "Meta":{
    "total-pages":1
  }
}

使用以下数据传输对象(为简洁起见,未发布参考类)。

public class TransactionDTO {
    private Data[] data;
    private Links links;
    private Meta meta;
    public Data[] getData () {  return data; }
    public void setData (Data[] data) { this.data = data; }
    public Links getLinks () { return links; }
    public void setLinks (Links links) { this.links = links; }
    public Meta getMeta () { return meta; }
    public void setMeta (Meta meta) { this.meta = meta; }
}

将DTO转换为Java对象的代码如下:

private TransactionDTO marshall(String accountTransactionsJSON) {
    ObjectMapper objectMapper = new ObjectMapper();
    TransactionDTO transactionDTO = null;
    try {
        transactionDTO = objectMapper.readValue(accountTransactionsJSON, TransactionDTO.class);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return transactionDTO;
}

我遇到了这个错误:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Data" (class xxx.dto.TransactionDTO), not marked as ignorable (3 known properties: "links", "data", "meta"])
 at [Source: java.io.StringReader@48f43b70; line: 2, column: 11] (through reference chain: xxx.dto.TransactionDTO["Data"])

我尝试了不同的方法来解决这个问题,例如:

objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

除此之外:

@JsonRootName(value = "data")

然而,我要么得到同样的问题,要么得到只包含 null 值的 TransactionDTO。

我猜问题出在 Data 字段上,但我不知道如何解决这个问题(这里的解决方案对我也无效)。

问题

  1. 有没有想法如何解决这个问题?
  2. 访问器的大小写应该反映 JSON 中的大小写吗?
4个回答

9

我使用这种方法解决了类似的问题。

ObjectMapper objectMapper = new ObjectMapper();

objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

7

Jackson默认区分大小写。尝试以下操作:

ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);

谢谢!已点赞!因为更加完整,所以标记另一个答案为已解决。 - Hey StackExchange

5
问题在于您的JSON属性名称(例如"Data")与Java属性名称(例如data)不匹配。 除了@psmagin的答案,还有两个替代选项可修复此问题:
  1. Keep your Java code unchanged. And in the JSON contents change all keys (the strings left from the :) from first-uppercase to first-lowercase:

    {
       "data":[
       {
         "accountId":"2009852923",
         "currency":"EUR",
         "nickname":"SA 01",
         "account":{
           "schemeName":"BBAN",
           "name":"SA 01",
           "identification":"2009852923"
       },
       ....
    }
    
  2. Keep the JSON contents unchanged. And in your Java-code use @JsonProperty annotations to tell Jackson the corresponding JSON property-names of your Java properties:

    public class TransactionDTO {
        private @JsonProperty("Data") Data[] data;
        private @JsonProperty("Links") Links links;
        private @JsonProperty("Meta") Meta meta;
        public Data[] getData () {  return data; }
        public void setData (Data[] data) { this.data = data; }
        public Links getLinks () { return links; }
        public void setLinks (Links links) { this.links = links; }
        public Meta getMeta () { return meta; }
        public void setMeta (Meta meta) { this.meta = meta; }
    }
    

    and in the same manner in your other Java classes (Links, Meta, Data, ...)

我更倾向于第一种选项,因为在JSON和Java中,采用首字母小写的属性命名是已经被广泛认可的最佳实践。


1
谢谢!注释解决了我的问题。已标记为已回答并点赞。 - Hey StackExchange

4

我遇到了这个错误,因为我并不想将所有的JSON字段映射到我的POJO(普通Java对象),只想映射其中的几个。所以它提示我标记它们为忽略。下面的示例展示了这个想法:

@JsonIgnoreProperties(ignoreUnknown = true)
public class Book {

@JsonProperty("kind")
private String kind;

@JsonProperty("id")
private String id;

@JsonProperty("volumeInfo")
private BookInfo bookInfo;

@Override
public String toString() {
    return "ClassPojo [kind = " + kind + ", id = " + id + ", bookInfo = " + bookInfo +"]";
}

另一方面,我的 Json 响应中包含了10多个字段。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接