Last active
June 25, 2019 02:49
-
-
Save seraphy/32f16fa1cef4077f53e16cea347cd543 to your computer and use it in GitHub Desktop.
JacksonでStringでない独自型のキーをもつMapをJSONにシリアライズ/デシリアライズする実装例
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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