Jackson 2.9からupdateValue/readerForUpdatingでデータのマージがされる

こんにちは。紅葉の季節ですね。 最近寒くて辛い。Spring Bootのアップデートもうまくいってなくて辛い。

今日も今日とて、アップデートでハマったメモを書きます。

ObjectMapper#readerForUpdatingを使っているあなた。気をつけましょう。

あるキーに対して、上記APIを使ってアップデートをかけた場合にCollection, Mapの場合 2.9からマージされるようになったようです。

以下のミニマムなケースがバージョン前後で非互換性を生むことになります。 安易に使用してはいけません。もちろん。

public class JacksonTest {
    
    @Test
    public void test() throws IOException {
        // setup: map
        HashMap<String, Object> map = new HashMap<>();
        ArrayList<String> list = new ArrayList<>();
        list.add("test");
        map.put("key", list);
        
        // setup: otherMap
        HashMap<String, Object> otherMap = new HashMap<>();
        otherMap.put("key", Collections.singletonList("test"));
        
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.valueToTree(otherMap);
        objectMapper.readerForUpdating(map)
            .readValue(jsonNode);
        
        // jackson 2.9から、同じキーの値はマージされる。
        JsonAssert.with(objectMapper.writeValueAsString(map))
            .assertEquals("$.key.size()", 2); // 2.8だとこのアサーションが落ちる。
    }
}

終わりに

気をつけましょう。 自分で調べた限りだと、この挙動は現状設定で対処出来ない部分です。アノテーションでも解決不可です。 ObjectMapper.setDefaultMergeableを使えば回避できそうです。 お疲れ様でした。コードを修正しましょう。

Jacksonの層でHackするのは辞めてほしい。