通过Jackson注释将具有大量属性的json反序列化为java类

时间:2017-07-13 08:01:41

标签: java json serialization jackson

所以我目前正在使用Jackson将JSON反序列化为java对象。一切都运作良好,但我也有一些领域,如:

对于这种JSON文件:

{
    "uid": 7,
    "asset": 123,
    "currency1_balance": 0,
    "currency2_balance": 0,

    ... ...

    "currencyN_balance": 0,
}

我们可以通过下面的java类反序列化它:

@Test
public void testBalanceJSON() throws IOException {
    // Read in the JSON from the example resources
    InputStream is = BalanceTest.class.getResourceAsStream("/example-balance-data.json");
    //Use Jackson to parse it
    ObjectMapper mapper = new ObjectMapper();
    Balance balance = mapper.readValue(is, Balance.class);
}

... ...

@JsonIgnoreProperties(ignoreUnknown = true)
public class Balance {
    private final BigDecimal uid;
    private final BigDecimal asset;
    private final BigDecimal currency1Balance;
    private final BigDecimal currency2Balance;
    // ... ...
    private final BigDecimal currencyNBalance;

    @JsonCreator
    public Balance(@JsonProperty("uid") BigDecimal uid, @JsonProperty("asset") BigDecimal asset,
                 @JsonProperty("currency1_balance") BigDecimal currency1Balance,
                 @JsonProperty("currency2_balance") BigDecimal currency2Balance,
                 // ... ...
                 @JsonProperty("currencyN_balance") BigDecimal currencyNBalance) {
                    this.uid = uid;
                    this.asset = asset;
                    this.currency1Balance = currency1Balance;
                    this.currency2Balance = currency2Balance;
                    // ... ...
                    this.currencyNBalance = currencyNBalance;
                }
}

在上面的例子中,我必须编写大量代码来处理" currencyN_balance"之间的映射。和" currencyNalance"。一旦添加/删除货币,我就必须相应地修改代码,这是非常不灵活的。 然后我找到了以下方法来自定义反序列化过程。

  @JsonCreator
  public static Balance Create(Map<String, Object> jsonMap) {
     //Resovle the map
     BigDecimal uid = new BigDecimal(jsonMap.get("uid").toString());
     BigDecimal asset = new BigDecimal(jsonMap.get("asset").toString());
     for (Map.Entry<String, Object> entry : jsonMap.entrySet()){
         if (entry.getKey().startsWith("currency")) {
            //Do something...
         }
     }
     //Then construct the Balance instance and return
  }

通过使用上面的方法,我可以摆脱枯燥和容易出错的映射。但是我不能利用注释来处理一些参数&#39;反序列化(例如,uid,资产)。

有没有什么方法可以结合上述两种技术的优势? (使用带有参数的注释,例如uid,资产,同时能够自定义货币映射)

感谢。

1 个答案:

答案 0 :(得分:1)

这是JSON的憎恶。那货币_ [1..n] _balance应该在一个数组中...因为它是一个数组,但是编码得很糟糕。

无论如何,这不是你的错(我希望)。为此你可以使用Jackson @JsonAnyGetter和@JsonAnySetter注释(如果你想序列化和反序列化这个类,否则你只能使用其中一个)。

例如

@JsonAnySetter
public void set(String name, String value) {
  //do funky transformation/assigment
}

杰克逊会用任何无法映射的属性调用该方法。因此,您可能需要添加一些逻辑来忽略您不感兴趣的属性。