Help us understand the problem. What is going on with this article?

Jacksonメモ

More than 3 years have passed since last update.

Jackson の使い方などのメモ
今後追加していく予定

JSON変換高速化

Jacksonでの JSON への変換時にボトルネックとなっている部分として、どうにも ObjectMapper のインスタンスの生成が遅い気がする。
さらに、マルチスレッドで並列に生成しようとすると、排他処理がかかっているのか(ソースを見ていないので違っていたらゴメンナサイ)、シリアルにJSON変換が行われているように見える。

そこで、ObjectMapperがスレッドセーフであれば、あらかじめ生成した ObjectMapper を使いまわす事で、処理の高速化を計れそう。

っということで、ObjectMapperがスレッドセーフか調査

http://wiki.fasterxml.com/JacksonFAQ

Is ObjectMapper thread-safe?

Short answer: yes

Long answer: yes, as long as you always configure instance before use, and do not call configure methods during operation (or synchronize such calls appropriately). Usually it is better to construct separate mapper instance if configurations differ in any case.

Further: it is beneficial to use just one instance (or small number of instances) for data binding; many optimizations for reuse (of symbol tables, some buffers) depend on ObjectMapper instances being reused.

For more information, check out JacksonFAQThreadSafety

どうやら、read/wirte中にObjectMapperの設定が変更されなければスレッドセーフということなので、
単純な使い方だけなら問題なさそう。

ジェネリクスのJSONデシリアライズ

ジェネリクスをJSONにシリアライズすることは特に意識しなくてもできるが、
それを再度デシリアライズしてオブジェクトに戻そうとすると、
JsonMappingException が発生してしまう。

これの解決策として、@JsonTypeInfo で型情報を一緒にJSONに出力することで、ジェネリクスでもJSONからオブジェクトにデシリアライズできる

サンプル
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, property="classType")
public abstract class SuperClass {
    public int id;
}

public class SubClass extends SuperClass {
    public String name;
}

public class DerivedClass extends SuperClass {
    public int number;
}

public class Array extends SuperClass {
    List<SuperClass> list = new ArrayList<SuperClass>();
}


public static void main() {

   SubClass sub = new SubClass();
   sub.id = 1234;
   sub.name = "aiueo";

   DerivedClass derived = new DerivedClass();
   derived.id = 5678;
   derived.number = 1;

   Array hoge = new Array();
   hoge.list.add(sub);
   hoge.list.add(derived);

   ObjectMapper mapper = new ObjectMapper();
   String json = mapper.writeValueAsString(hoge);

   System.out.println(json);

   Array hoge2 = mapper.readValue(json, Array.class);
   String json2 = mapper.writeValueAsString(hoge2);
   System.out.println("desirialize success ?");
   System.out.println(json.equals(json2));
}

結果
{
    "classType": "Array",
    "id": 0,
    "list": [
        {
            "classType": "SubClass",
            "id": 1234,
            "name": "aiueo"
        },
        {
            "classType": "DerivedClass",
            "id": 5678,
            "number": 1
        }
    ]
}

desirialize success ?
true

JsonTypeInfo

■ use 属性

型情報の出力方法を指定。
今回は Id.CLASS を指定しているので、パッケージを含めたクラス名で出している

■ propety 属性

JSON出力時のキー名を指定。

制限

サンプルにある Array クラスが以下のようになっている場合、JsonTypeInfo が出力されません。
おそらく list 内で、JsonTypeInfo を出力できないクラスが混じる可能性がある場合は出力しないようになっているのではないかと思われ・・・

public class Array extends SuperClass {
    //List<SuperClass> list = new ArrayList<SuperClass>();
    List<Object> list = new ArrayList<Object>();
}

デシリアライズ時のコンストラクタ指定

こちら

Jackson でオブジェクトの Serializer を作ってみる

こちら

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away