Skip to content

Instantly share code, notes, and snippets.

@s-j
Last active August 29, 2015 13:56
Show Gist options
  • Save s-j/8864592 to your computer and use it in GitHub Desktop.
Save s-j/8864592 to your computer and use it in GitHub Desktop.
Deserializing multi-level polymorphic types with Jackson.
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.base.Strings;
public final class Example {
private Example() { }
@JsonDeserialize(using = FilterDeserializer.class)
public abstract static class Filter {
public String type;
public String operator;
}
public abstract static class StringFilter extends Filter {
public String variable;
}
public static final class Equality extends StringFilter {
public String value;
public Equality(String type, String operator, String variable, String value) {
this.type = type;
this.operator = operator;
this.variable = variable;
this.value = value;
}
}
public static final class Match extends StringFilter {
public String pattern;
public Match(String type, String operator, String variable, String pattern) {
this.type = type;
this.operator = operator;
this.variable = variable;
this.pattern = pattern;
}
}
public static final class FilterDeserializer extends JsonDeserializer<Filter> {
@Override
public Filter deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
String type = node.path("type").asText();
String operator = node.path("operator").asText();
switch (type) {
case "string" :
if (Strings.isNullOrEmpty(operator)) {
operator = "equals";
}
switch (operator) {
case "equals" :
return new Equality(type, operator, node.path("variable").asText(), node.path("value").asText());
case "matches" :
return new Match(type, operator, node.path("variable").asText(), node.path("pattern").asText());
default:
throw new IllegalArgumentException("Unknown operator");
}
default:
throw new IllegalArgumentException("Unknown filter type");
}
}
}
public static void main(String[] args) {
Filter f = JSONUtil.fromString("{\"type\":\"string\",\"variable\":\"foo\",\"value\":\"bar\"}", Filter.class);
System.out.println(JSONUtil.toString(f));
f = JSONUtil.fromString("{\"type\":\"string\",\"variable\":\"foo\",\"operator\":\"matches\",\"pattern\":\"bar*\"}", Filter.class);
System.out.println(JSONUtil.toString(f));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment