I have a class hierarchy that is somewhat like below, with a custom Converter
The FieldValueConverter#deserialize
is NOT being called in my JerseyTest
. Instead, it uses the default GensonJsonConverter which complains it can't find the appropriate constructor. (Caused by: com.owlike.genson.JsonBindingException: No constructor has been found for type class com.searchdata.actions.api.FieldValue
)
How do I get it to be used?
Registration
The converter for the FieldValue
s (see below), which I register in a Jersey Application
like this:
Genson genson = new GensonBuilder()
.withBundle(new JAXBBundle())
.withConverter(new FieldValueConverter(), FieldValue.class)
.setSkipNull(true)
.create();
register(new GensonJaxRSFeature().use(genson));
FieldValueConverter
public class FieldValueConverter implements Converter<FieldValue> {
private static final Logger LOG = LoggerFactory.getLogger(FieldValueConverter.class);
public void serialize(FieldValue fieldValue, ObjectWriter writer, Context ctx) throws Exception {
LOG.info("Serializing fieldValue:{}", fieldValue);
writer.beginObject();
writer.writeString("type", fieldValue.getType().name())
.writeString("value", fieldValue.getValue().toString())
.writeString("field", fieldValue.getField());
writer.endObject();
LOG.info("..Done!", fieldValue);
}
/* You don't have to worry for the object being null here, if it is null Genson will
handle it for you. */
public FieldValue deserialize(ObjectReader reader, Context ctx) throws Exception {
LOG.info("Deserializing fieldValue...");
reader.beginObject();
String stringValue=null;
FieldType type= FieldType.STRING;
String fieldKey= null;
while (reader.hasNext()) {
reader.next();
if ("type".equals(reader.name())) {
type = FieldType.valueOf(reader.valueAsString());
} else if ("field".equals(reader.name())) {
fieldKey = reader.valueAsString();
} else if ("value".equals(reader.name())) {
stringValue = reader.valueAsString();
} else {
reader.skipValue();
}
}
Item
public class Item
{
@Schema(name = "id", description = "The id of an item")
private String id;
@Schema(name = "values", description = "The fields with values for this action")
private List<FieldValue> values;
}
FieldValue
@Schema(name = "FieldValue")
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
public class FieldValue {
@Schema(name = "field", description = "The technical name of the field")
private String field;
@Schema(name = "type", description = "The type of the field")
private FieldType type;
@Schema(name = "value", description = "The value of a field", oneOf = {Integer.class, String.class, Date.class, Double.class})
private Serializable value;
public FieldValue(final String field, final String string) {
setField(field);
setValue(string);
setType(FieldType.STRING);
}
public FieldValue(final String field, final Long number) {
setField(field);
setValue(number);
setType(FieldType.LONG);
}