0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Jackson】JsonSerializerで値を変換してシリアライズする場合、defaultSerializeValueを使うべき

Posted at

TL;DR

以下のサンプルコードの通りです。
findValueSerializerを使った場合、最悪シリアライズ時にエラーが出るため、defaultSerializeValueを使うべきです。

@Override
public void serialize(
  Foo value,
  JsonGenerator gen,
  SerializerProvider provider
) throws IOException {
  // 任意の変換処理
  Bar converted = convert(value);

  // 以下のように書くのが望ましい
  provider.defaultSerializeValue(converted, gen);

  // 以下のように書くのはNG
  // provider.findValueSerializer(converted.getClass()).serialize(converted, gen, provider);
}

状況想定

以下のような状況を想定しています。

  • 入力を任意の型に変換してシリアライズしたい
  • ObjectMapperに登録されているシリアライザーは使いまわしたい
    • 例: Jacksonからデフォルトで提供されているものや自作した共通シリアライザー

単純に値を書き込むだけで済む場合は、gen.writeStringgen.writeNumberなど、よりシンプルな方法を使うこともできます。

defaultSerializeValueを使うべき理由

単純にシンプルという以外にも、findValueSerializerを使った場合にはエラーを引き起こすリスクが有るためです。

コンテキストが正しく伝播する

findValueSerializerを使った場合、表面上は正しく動いているように見えても、実際にはJacksonのシリアライズに関するコンテキスト伝播の仕組みが上手く働いていません。
これによって、複雑なシリアライズ処理が期待通り動かなかったり、最悪エラーになったりします。

自分はこの方法でMapを書き込んだ所、KeySerializerが見つからなくなってエラーとなるケースに遭遇したことがあります。

nullの考慮が不要

defaultSerializeValueにはnullの考慮が有るため、サンプルコードでいうconvertnullを返した場合を気にする必要はありません。

一方、findValueSerializerを使う場合、nullに対してはfindNullValueSerializerを使うべきです。
つまり、正確を期するなら以下のように書くべきで、より複雑になります。

// 任意の変換処理
Bar converted = convert(value);

// 正確に書くと、より複雑になって嬉しくない
JsonSerializer<*> ser = converted != null
  ? provider.findValueSerializer(converted.getClass())
  : provider.findNullValueSerializer(null);

provider.findValueSerializer(converted.getClass()).serialize(converted, gen, provider);

参考

以下で教えて頂きました

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?