X. Wo Satuk X. Wo Satuk - 6 months ago 42
JSON Question

Deserializing Guava's Table with Jackson throws "JsonMappingException: No suitable constructor found for type"

I'm using

. I'm trying to deserialize a Table from JSON, but I'm getting an exception.

My code is:

public void jsonTable() throws IOException {
Table<String, String, String> table = HashBasedTable.create();
table.put("row1", "col1", "cell11");
table.put("row1", "col2", "cell12");
table.put("row2", "col1", "cell21");
table.put("row2", "col2", "cell22");

ObjectMapper mapper = new ObjectMapper()
.registerModule(new GuavaModule());

String tableJson = mapper.writeValueAsString(table);

Table<String, String, String> deserializedTable = mapper.readValue(tableJson, HashBasedTable.class);

The exception thrown at the last line is:

com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.google.common.collect.HashBasedTable]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: {"row1":{"col2":"cell12","col1":"cell11"},"row2":{"col2":"cell22","col1":"cell21"}}; line: 1, column: 2]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:255)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1130)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:298)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3807)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2797)
at com.gk.dfm.repository.impl.JsonTableTest.jsonTable(JsonTableTest.java:31)

It makes sense, since HashBasedTable has no default constructor. We should construct it using
. How can I tell it to Jackson though?

On this page I found how to deserialize Guava's Multimap:

public void convert() throws JsonParseException, JsonMappingException,
JsonProcessingException, IOException {

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new GuavaModule());

Multimap<String, NavItem> navs = objectMapper.readValue(
Multimap.class, String.class, NavItem.class));


assertThat(navs.keys(), hasItems("123455", "999999"));

How can I apply it to a Table? There is no such thing as constructTableLikeType.


First, try using jackson-datatypes-collections instead of jackson-datatype-guava, because it has been moved under jackson-datatype-collections to simplify management, release process.

The support for Guava's Table seems to be incomplete, because there's an open issue for adding (de)serializer for it. Since it's open source, you can do it yourself (please contribute back if you do so!) - you can use what other other people wrote, like this pull request in old repository (also see test for Table which indicates serializing is supported, but no deserializing though).