Skip to content

Instantly share code, notes, and snippets.

@robinhowlett
Last active September 4, 2022 20:27
Show Gist options
  • Save robinhowlett/1ef8a82584e9ea36ed04 to your computer and use it in GitHub Desktop.
Save robinhowlett/1ef8a82584e9ea36ed04 to your computer and use it in GitHub Desktop.
Building a Custom Jackson Deserializer
package com.robinhowlett.blog;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
/**
* Deserializer that case-insensitively deserializes
* "yes", "no", and null JSON field values to
* true, false, and false respectively
*
* @author robin
*
*/
public class YesNoBooleanDeserializer extends JsonDeserializer<Boolean> {
protected static final String NO = "no";
protected static final String YES = "yes";
/* (non-Javadoc)
* @see com.fasterxml.jackson.databind.JsonDeserializer#deserialize(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.DeserializationContext)
*/
@Override
public Boolean deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonToken currentToken = jp.getCurrentToken();
if (currentToken.equals(JsonToken.VALUE_STRING)) {
String text = jp.getText().trim();
if (YES.equalsIgnoreCase(text)) {
return Boolean.TRUE;
} else if (NO.equalsIgnoreCase(text)) {
return Boolean.FALSE;
}
throw ctxt.weirdStringException(text, Boolean.class,
"Only \"" + YES + "\" or \"" + NO + "\" values supported");
} else if (currentToken.equals(JsonToken.VALUE_NULL)) {
return getNullValue();
}
throw ctxt.mappingException(Boolean.class);
}
@Override
public Boolean getNullValue() {
return Boolean.FALSE;
}
}
package com.robinhowlett.blog;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
/**
* Test that "yes", "no" and null values that are deserialized
* with {@link YesNoBooleanDeserializer} return true, false, and
* false respectively
*
* @author robin
*
*/
public class YesNoBooleanDeserializerTest {
private ObjectMapper mapper;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
mapper = new ObjectMapper();
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
mapper = null;
}
@Test
public void yes() throws JsonParseException, IOException {
String yes = "\"" + YesNoBooleanDeserializer.YES + "\"";
Boolean result = deserialize(yes);
assertTrue(result);
result = deserialize(yes.toUpperCase());
assertTrue(result);
}
@Test
public void no() throws JsonParseException, IOException {
String no = "\"" + YesNoBooleanDeserializer.NO + "\"";
Boolean result = deserialize(no);
assertFalse(result);
result = deserialize(no.toUpperCase());
assertFalse(result);
}
@Test
public void nullValue() throws JsonParseException, IOException {
// null values must deserialize as Boolean.FALSE to support primitives
Boolean result = deserialize(null);
assertFalse(result);
}
@Test(expected=JsonMappingException.class)
public void neitherYesOrNo() throws JsonParseException, IOException {
deserialize("\"never\"");
}
private Boolean deserialize(String yesOrNo) throws IOException, JsonParseException,
JsonProcessingException {
TestObject testObject = mapper.readValue("{\"exists\":" + yesOrNo + "}", TestObject.class);
return testObject.getExists();
}
private static class TestObject {
@JsonDeserialize(using = YesNoBooleanDeserializer.class)
private final Boolean exists = null;
public Boolean getExists() {
return exists;
}
}
}
@devendrashinde
Copy link

Thank you, it works

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment