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>();
}