CustomPTVMatchersTest.java
package com.fasterxml.jackson.databind.jsontype.vld;
import java.util.TimeZone;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import com.fasterxml.jackson.databind.testutil.DatabindTestUtil;
import static org.junit.jupiter.api.Assertions.*;
public class CustomPTVMatchersTest extends DatabindTestUtil
{
static abstract class CustomBase {
public int x = 3;
}
static class CustomGood extends CustomBase {
protected CustomGood() { }
public CustomGood(int x) {
super();
this.x = x;
}
}
static class CustomBad extends CustomBase {
protected CustomBad() { }
public CustomBad(int x) {
super();
this.x = x;
}
}
static final class ObjectWrapper {
public Object value;
protected ObjectWrapper() { }
public ObjectWrapper(Object v) { value = v; }
}
/*
/**********************************************************************
/* Test methods
/**********************************************************************
*/
@Test
public void testCustomBaseMatchers() throws Exception
{
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
.allowIfBaseType(new BasicPolymorphicTypeValidator.TypeMatcher() {
@Override
public boolean match(MapperConfig<?> ctxt, Class<?> base) {
// Allow types within our packages
return base.getName().startsWith("com.fasterxml.");
}
})
.build();
ObjectMapper mapper = jsonMapperBuilder()
.activateDefaultTyping(ptv, DefaultTyping.NON_FINAL)
.build();
// First: in this case, allow "Bad" one too (note: default typing based on
// runtime type here)
final String goodJson = mapper.writeValueAsString(new CustomBad(42) );
CustomBase result = mapper.readValue(goodJson, CustomBase.class);
assertEquals(CustomBad.class, result.getClass());
// but other types not so good
final String badJson = mapper.writeValueAsString(TimeZone.getDefault());
try {
mapper.readValue(badJson, TimeZone.class);
fail("Should not pass");
} catch (InvalidTypeIdException e) {
verifyException(e, "Could not resolve type id 'java.util.TimeZone'");
verifyException(e, "as a subtype of");
}
assertEquals(CustomBad.class, result.getClass());
}
@Test
public void testCustomSubtypeMatchers() throws Exception
{
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
.allowIfSubType(new BasicPolymorphicTypeValidator.TypeMatcher() {
@Override
public boolean match(MapperConfig<?> ctxt, Class<?> clazz) {
// Allow anything that looks "Good" :)
return clazz.getSimpleName().endsWith("Good");
}
})
.build();
ObjectMapper mapper = jsonMapperBuilder()
.activateDefaultTyping(ptv, DefaultTyping.NON_FINAL)
.build();
// First: allow "Good" one:
final String goodJson = mapper.writeValueAsString(new ObjectWrapper(new CustomGood(42) ));
ObjectWrapper w = mapper.readValue(goodJson, ObjectWrapper.class);
assertNotNull(w);
assertNotNull(w.value);
assertEquals(CustomGood.class, w.value.getClass());
// Then something else
final String badJson = mapper.writeValueAsString(new ObjectWrapper(new CustomBad(42) ));
try {
mapper.readValue(badJson, ObjectWrapper.class);
fail("Should not pass");
} catch (InvalidTypeIdException e) {
verifyException(e, "Could not resolve type id 'com.fasterxml.jackson.");
verifyException(e, "as a subtype of");
}
}
}