Jacksonでインタフェースと実装クラスがわかれているときにデシリアライズする方法
インタフェースクラス(Child.class
)と、実装クラス(ChildImpl.class
)がわかれているとき、そのままデシリアライズしようとすると、
public class DeserTest {
static interface Child {
public String getMemo();
public void setMemo(String memo);
}
static class ChildImpl implements Child {
private String memo;
public String getMemo() { return memo; }
public void setMemo(String memo) { this.memo = memo; }
}
static class HogeBean {
private int id;
private String name;
private URL url;
private List<Child> list;
private Map<Integer, Child> map;
public List<Child> getList() { return list; }
public void setList(List<Child> list) { this.list = list; }
public Map<Integer, Child> getMap() { return map; }
public void setMap(Map<Integer, Child> map) { this.map = map; }
public int getId() { return id; }
private void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public URL getUrl() { return url; }
public void setUrl(URL url) { this.url = url; }
}
public static void main(String[] args) throws Exception {
String text =
"{\"list\":[{\"memo\":\"めもですが\"},{\"memo\":\"めもですが22\"},{\"memo\":123}],"
+ "\"id\":-773504340,"
+ "\"name\":\"あい うえ男\","
+ "\"url\":\"http://www.hoge.co.jp\","
+ "\"map\":{\"999\":{\"memo\":\"map-999\"},\"222\":{\"memo\":\"map-222\"}}"
+ "}";
ObjectMapper mapper = new ObjectMapper();
HogeBean obj = mapper.readValue(text, HogeBean.class);
}
}
インタフェースクラスをインスタンス化しようとするので、例外がスローされる。
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException:
Can not construct instance of DeserTest$Child, problem: abstract types either
need to be mapped to concrete types, have custom deserializer,
or be instantiated with additional type information
このようなときは、Java Bean がインターフェースと実装に分離している場合にあるように、@JsonTypeInfo
アノテーションを使って対応できる。
けれど、ソースに手を入れてアノテーションを設定することができないこともある。@JsonTypeInfo
アノテーションを使わずに、Childインタフェースの実装クラスはChildImplクラスであることをObjectMapperに伝えるにはSimpleModule#addAbstractTypeMapping()
を使うといいようだ。
import com.fasterxml.jackson.databind.module.SimpleModule;
...
SimpleModule module = new SimpleModule();
module.addAbstractTypeMapping(Child.class, ChildImpl.class);
mapper.registerModule(module);
HogeBean obj = mapper.readValue(text, HogeBean.class);
System.out.println(obj.getMap());
System.out.println(obj.getMap().getClass());
結果
{999=DeserTest\$ChildImpl@35af4d51, 222=DeserTest$ChildImpl@7fd1c60}
class java.util.LinkedHashMap
Mapインタフェースの実装をHashMapクラスに設定すると、当然そうなる。
SimpleModule module = new SimpleModule();
module.addAbstractTypeMapping(Child.class, ChildImpl.class);
module.addAbstractTypeMapping(Map.class, HashMap.class);
mapper.registerModule(module);
...
結果
{222=DeserTest\$ChildImpl@1f78a4e8, 999=DeserTest$ChildImpl@29928b7c}
class java.util.HashMap
Author And Source
この問題について(Jacksonでインタフェースと実装クラスがわかれているときにデシリアライズする方法), 我々は、より多くの情報をここで見つけました https://qiita.com/rhinotake/items/258a65155e850d08c015著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .