Jacksonでコンストラクタを利用してデシリアライズ
Jackson は引数なしコンストラクタが必要、というblogを目にしましたが、正しくありません。
-
@JsonCreator
を付与することでそのコンストラクタを使ってデシリアライズするように指示できます。-
コンストラクタが1つしか無い場合は省略できます。
-
-
JSON プロパティと Java フィールドのマッピングは
@JsonProperty
で行えます。-
jackson-module-parameter-names
を利用すると、メソッドシグネチャのパラメータを利用してマッピングできるので、この設定を省略できます。-
ちなみに、この機能は Jackson 3.x では本体(
jackson-databind
)に統合されるようです。(2.x は Java7 以前もサポート対象にしているので Java8 以降の機能は切り出しているみたいです)
-
-
というわけで、今 Jackson を使うなら、次のようにすれば良いです:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import lombok.RequiredArgsConstructor;
import lombok.Value;
public class JavaMain {
public static final String JSON_TEXT = "{\"name\": \"Bob\", \"age\": 30 }";
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper om = new ObjectMapper();
om.registerModule(new ParameterNamesModule());
Person person = om.readValue(JSON_TEXT, Person.class);
System.out.println(person);
}
}
@Value
// ちなみに Lombok を使っていて自動生成されるコンストラクタにアノテーションを付与したい場合は:
// @RequiredArgsConstructor(onConstructor = @__(@JsonCreator))
class Person {
String name;
int age;
}
Java17 なら record
class に置き換えられるので、 Person
はもはや Lombok を利用しなくとも簡単に書けるようになりました:
record Person(String name, int age) {
}
コンパイルオプションに、メソッドシグネチャに仮引数名を残す設定 -parameters
を追加する必要もあります。
これは、 maven-compiler-plugin
の parameters
を true
にすることで実現できます。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<parameters>true</parameters>
</configuration>
プラグインのバージョンが古い(3.6.2
未満)場合はこのオプションが無いので、代わりに compilerArgs
で設定します。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
...
関連: