JacksonでJSONのフィールドの命名規則を定義する

エキサイト株式会社メディア事業部エンジニアの佐々木です。JVMJSONを扱うときのライブラリであるJacksonのフィールド名の規則を定義します。

環境

Javaバージョン

$ java --version
openjdk 17.0.1 2021-10-19
OpenJDK Runtime Environment (build 17.0.1+12-39)
OpenJDK 64-Bit Server VM (build 17.0.1+12-39, mixed mode, sharing)

Gradleバージョン

$ ./gradlew --version

------------------------------------------------------------
Gradle 7.6
------------------------------------------------------------

Build time:   2022-11-25 13:35:10 UTC
Revision:     daece9dbc5b79370cc8e4fd6fe4b2cd400e150a8

Kotlin:       1.7.10
Groovy:       3.0.13
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          17.0.1 (Oracle Corporation 17.0.1+12-39)
OS:           Mac OS X 12.5 aarch64

Gradle依存関係

dependencies {
         compileOnly 'org.projectlombok:lombok:1.18.24'
    annotationProcessor 'org.projectlombok:lombok:1.18.24'
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.14.2'
}

UpperCamelCase のときのJacksonの設定

JacksonはデフォルトでLower Camel Case を使用します。なので、JSONのフィールド名が先頭大文字だと、エラーになります。 下記コードは先頭大文字のキャメルケースなので、実行時にエラーとなります。

public class JacksonNamingRuleTest {
    private static String upperCamelCaseText = """
            [
             {
            "IndexId": 0
            ,"FirstName": "index1"
             },
            {
            "IndexId": 1
            ,"FirstName": "index2"
              }
            ]
            """;
    public static void main(String[] args) throws IOException {

        ObjectMapper objectMapper = new ObjectMapper();
        List<UpperCamelCaseForm> upperCamelCaseForms = objectMapper.readValue(upperCamelCaseText, new TypeReference<>() {
        });
        log.info("upper camel case: {}", upperCamelCaseForms);

    }

    @Data
    static class UpperCamelCaseForm {
       private int IndexId;
       private String FirstName;
    }
}


実行時... 
====
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "IndexId" (class com.example.demo.JacksonNamingRuleTest$UpperCamelCaseForm), not marked as ignorable (2 known properties: "firstName", "indexId"])

これを修正するには、データクラスにアノテーションをつけるだけになります。

    @Data
    @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class)  // <- これを追加する
    static class UpperCamelCaseForm {
       private int IndexId;
       private String FirstName;
    }

これで正常に動作します。

SnakeCase のときのJacksonの設定

SnakeCaseのときも、データクラスにアノテーションをつけるだけになります。

    @Data
    @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) // <- これを追加する
    static class SnakeCaseForm {
        private int IndexId;
        private String FirstName;
    }

キャメルケースやスネークケースが混在する場合

既存のAPI等であるのが、キャメルケースやスネークケースが混在する場合があります。その場合は、ベースをどちらかに決めて、@JsonPropertyアノテーションを使用し、回避していきます。 下記は、ベースをアッパーキャメルケースにしてにして、FirstNameのプロパティがスネークケースの場合の例になります。

    @Data
    @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class)
    static class SnakeCaseForm {
        private int indexId;
        
        @JsonProperty("first_name")  // <- ここにスネークケースのプロパティ名を記述
        private String FirstName;
    }

まとめ

アノテーションひとつで実際のコードの変更は行わずに挙動を変えることができるのは便利なです。しかし、実行してみるまでわからないや覚えることが多いなどの課題もありますが、やはり便利です。 面倒な処理はアノテーションに閉じ込めて重要なビジネスロジックに専念していけるようにしたいです。

最後に

エキサイトではフロントエンジニア、バックエンドエンジニア、アプリエンジニアを随時募集しております。長期インターンも歓迎していますので、興味があれば連絡いただければと思います。

カジュアル面談はこちらになります! meety.net

募集職種一覧はこちらになります!(カジュアルからもOK) www.wantedly.com