Skip to content

Instantly share code, notes, and snippets.

@seraphy
Last active June 25, 2019 02:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seraphy/32f16fa1cef4077f53e16cea347cd543 to your computer and use it in GitHub Desktop.
Save seraphy/32f16fa1cef4077f53e16cea347cd543 to your computer and use it in GitHub Desktop.
JacksonでStringでない独自型のキーをもつMapをJSONにシリアライズ/デシリアライズする実装例
package jp.seraphyware.example.java8learn.json;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
/**
* JacksonでStringでない独自型のキーをもつMapをJSONにシリアライズ/デシリアライズする実装例。
*
* JSONのキーは数値または文字列のような単純型でなければならないので、
* 独自型のオブジェクトをキーにする場合は、JSON変換したものを文字列として扱うように工夫すれば良い。
*
* 参考: https://gist.github.com/crimsoncor/3335224
*/
public class MapJsonExample {
/**
* キーの型
*/
public static class Bar {
private String name;
private Date born;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setBorn(Date born) {
this.born = born;
}
public Date getBorn() {
return born;
}
@Override
public String toString() {
return "Bar [name=" + name + ", born=" + born + "]";
}
}
/**
* Barをキーの型とするMapを保持するクラス
*/
public static class Foo {
private String oid;
@JsonSerialize(keyUsing = MyCustomSerializer.class)
@JsonDeserialize(keyUsing = MyCustomDeserializer.class)
private Map<Bar, String> map = new HashMap<>();
public String getOid() {
return oid;
}
public void setOid(String oid) {
this.oid = oid;
}
public Map<Bar, String> getMap() {
return map;
}
@Override
public String toString() {
return "Foo [map=" + map + "]";
}
}
/**
* マッパーのキャッシュ
*/
private static final ObjectMapper mapper = new ObjectMapper();
/**
* キーをJSONに変換する。(このキーのJSONは、mapのキーとしてエスケープされた文字列として組み込まれる。)
*/
public static class MyCustomSerializer extends JsonSerializer<Bar> {
@Override
public void serialize(Bar value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeFieldName(mapper.writeValueAsString(value));
}
}
/**
* JSONからキー型に変換する
*/
public static class MyCustomDeserializer extends KeyDeserializer {
@Override
public Bar deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return mapper.readValue(key, Bar.class);
}
}
/**
* 実験
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// テストデータの作成
Foo foo = new Foo();
foo.setOid("aaaa");
for (int idx = 0; idx < 3; idx++) {
Bar bar = new Bar();
bar.setName("name" + idx);
bar.setBorn(new Date());
foo.getMap().put(bar, "qqq" + idx);
}
// JSONへの変換
String json = mapper.writeValueAsString(foo);
System.out.println("json=" + json);
// JSONからの変換
Foo foo2 = mapper.readValue(json, Foo.class);
System.out.println("foo2=" + foo2);
for (Map.Entry<Bar, String> entry : foo2.getMap().entrySet()) {
Bar bar = entry.getKey();
String val = entry.getValue();
System.out.println(bar + "=" + val);
}
}
}
json={"oid":"aaaa","map":{"{\"name\":\"name0\",\"born\":1561430750542}":"qqq0","{\"name\":\"name2\",\"born\":1561430750542}":"qqq2","{\"name\":\"name1\",\"born\":1561430750542}":"qqq1"}}
foo2=Foo [map={Bar [name=name0, born=Tue Jun 25 11:45:50 JST 2019]=qqq0, Bar [name=name2, born=Tue Jun 25 11:45:50 JST 2019]=qqq2, Bar [name=name1, born=Tue Jun 25 11:45:50 JST 2019]=qqq1}]
Bar [name=name0, born=Tue Jun 25 11:45:50 JST 2019]=qqq0
Bar [name=name2, born=Tue Jun 25 11:45:50 JST 2019]=qqq2
Bar [name=name1, born=Tue Jun 25 11:45:50 JST 2019]=qqq1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment