| |
| package com.fasterxml.jackson.databind.creators; |
| |
| import java.io.IOException; |
| import java.util.List; |
| import java.util.Map; |
| |
| import com.fasterxml.jackson.annotation.*; |
| import com.fasterxml.jackson.core.*; |
| import com.fasterxml.jackson.databind.*; |
| import com.fasterxml.jackson.databind.annotation.JsonDeserialize; |
| |
| public class TestCreators2 extends BaseMapTest |
| { |
| static class HashTest |
| { |
| final byte[] bytes; |
| final String type; |
| |
| @JsonCreator |
| public HashTest(@JsonProperty("bytes") @JsonDeserialize(using = BytesDeserializer.class) final byte[] bytes, |
| @JsonProperty("type") final String type) |
| { |
| this.bytes = bytes; |
| this.type = type; |
| } |
| } |
| |
| static class BytesDeserializer extends JsonDeserializer<byte[]> |
| { |
| @Override |
| public byte[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { |
| String str = jp.getText(); |
| return str.getBytes("UTF-8"); |
| } |
| } |
| |
| static class Primitives |
| { |
| protected int x = 3; |
| protected double d = -0.5; |
| protected boolean b = true; |
| |
| @JsonCreator |
| public Primitives(@JsonProperty("x") int x, |
| @JsonProperty("d") double d, |
| @JsonProperty("b") boolean b) |
| { |
| this.x = x; |
| this.d = d; |
| this.b = b; |
| } |
| } |
| |
| protected static class Test431Container { |
| protected final List<Item431> items; |
| |
| @JsonCreator |
| public Test431Container(@JsonProperty("items") final List<Item431> i) { |
| items = i; |
| } |
| } |
| |
| @JsonIgnoreProperties(ignoreUnknown = true) |
| protected static class Item431 { |
| protected final String id; |
| |
| @JsonCreator |
| public Item431(@JsonProperty("id") String id) { |
| this.id = id; |
| } |
| } |
| |
| // Test class for verifying that creator-call failures are reported as checked exceptions |
| static class BeanFor438 { |
| @JsonCreator |
| public BeanFor438(@JsonProperty("name") String s) { |
| throw new IllegalArgumentException("I don't like that name!"); |
| } |
| } |
| |
| static class MapBean |
| { |
| protected Map<String,Long> map; |
| |
| @JsonCreator |
| public MapBean(Map<String, Long> map) { |
| this.map = map; |
| } |
| } |
| |
| // For [JACKSON-470]: should be appropriately detected, reported error about |
| static class BrokenCreatorBean |
| { |
| protected String bar; |
| |
| @JsonCreator |
| public BrokenCreatorBean(@JsonProperty("bar") String bar1, @JsonProperty("bar") String bar2) { |
| bar = ""+bar1+"/"+bar2; |
| } |
| } |
| |
| // For [JACKSON-541]: should not need @JsonCreator if SerializationFeature.AUTO_DETECT_CREATORS is on. |
| static class AutoDetectConstructorBean |
| { |
| protected final String foo; |
| protected final String bar; |
| |
| public AutoDetectConstructorBean(@JsonProperty("bar") String bar, |
| @JsonProperty("foo") String foo){ |
| this.bar = bar; |
| this.foo = foo; |
| } |
| } |
| |
| static class BustedCtor { |
| @JsonCreator |
| BustedCtor(@JsonProperty("a") String value) { |
| throw new IllegalArgumentException("foobar"); |
| } |
| } |
| |
| static class IgnoredCtor |
| { |
| @JsonIgnore |
| public IgnoredCtor(String arg) { |
| throw new RuntimeException("Should never use this constructor"); |
| } |
| |
| public IgnoredCtor() { } |
| } |
| |
| abstract static class AbstractBase { |
| @JsonCreator |
| public static AbstractBase create(Map<String,Object> props) |
| { |
| return new AbstractBaseImpl(props); |
| } |
| } |
| |
| static class AbstractBaseImpl extends AbstractBase |
| { |
| protected Map<String,Object> props; |
| |
| public AbstractBaseImpl(Map<String,Object> props) { |
| this.props = props; |
| } |
| } |
| |
| static interface Issue700Set extends java.util.Set<Object> { } |
| |
| static class Issue700Bean |
| { |
| protected Issue700Set item; |
| |
| @JsonCreator |
| public Issue700Bean(@JsonProperty("item") String item) { } |
| |
| public String getItem() { return null; } |
| } |
| |
| /* |
| /********************************************************** |
| /* Test methods |
| /********************************************************** |
| */ |
| |
| private final ObjectMapper MAPPER = new ObjectMapper(); |
| |
| public void testExceptionFromConstructor() throws Exception |
| { |
| try { |
| MAPPER.readValue("{}", BustedCtor.class); |
| fail("Expected exception"); |
| } catch (JsonMappingException e) { |
| verifyException(e, ": foobar"); |
| // also: should have nested exception |
| Throwable t = e.getCause(); |
| assertNotNull(t); |
| assertEquals(IllegalArgumentException.class, t.getClass()); |
| assertEquals("foobar", t.getMessage()); |
| } |
| } |
| |
| public void testSimpleConstructor() throws Exception |
| { |
| HashTest test = MAPPER.readValue("{\"type\":\"custom\",\"bytes\":\"abc\" }", HashTest.class); |
| assertEquals("custom", test.type); |
| assertEquals("abc", new String(test.bytes, "UTF-8")); |
| } |
| |
| // Test for [JACKSON-372] |
| public void testMissingPrimitives() throws Exception |
| { |
| Primitives p = MAPPER.readValue("{}", Primitives.class); |
| assertFalse(p.b); |
| assertEquals(0, p.x); |
| assertEquals(0.0, p.d); |
| } |
| |
| public void testJackson431() throws Exception |
| { |
| final Test431Container foo = MAPPER.readValue( |
| "{\"items\":\n" |
| +"[{\"bar\": 0,\n" |
| +"\"id\": \"id123\",\n" |
| +"\"foo\": 1\n" |
| +"}]}", |
| Test431Container.class); |
| assertNotNull(foo); |
| } |
| |
| // Catch and rethrow exceptions that Creator methods throw |
| public void testJackson438() throws Exception |
| { |
| try { |
| MAPPER.readValue("{ \"name\":\"foobar\" }", BeanFor438.class); |
| fail("Should have failed"); |
| } catch (Exception e) { |
| if (!(e instanceof JsonMappingException)) { |
| fail("Should have received JsonMappingException, caught "+e.getClass().getName()); |
| } |
| verifyException(e, "don't like that name"); |
| // Ok: also, let's ensure root cause is directly linked, without other extra wrapping: |
| Throwable t = e.getCause(); |
| assertNotNull(t); |
| assertEquals(IllegalArgumentException.class, t.getClass()); |
| verifyException(e, "don't like that name"); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void testIssue465() throws Exception |
| { |
| final String JSON = "{\"A\":12}"; |
| |
| // first, test with regular Map, non empty |
| Map<String,Long> map = MAPPER.readValue(JSON, Map.class); |
| assertEquals(1, map.size()); |
| assertEquals(Integer.valueOf(12), map.get("A")); |
| |
| MapBean bean = MAPPER.readValue(JSON, MapBean.class); |
| assertEquals(1, bean.map.size()); |
| assertEquals(Long.valueOf(12L), bean.map.get("A")); |
| |
| // and then empty ones |
| final String EMPTY_JSON = "{}"; |
| |
| map = MAPPER.readValue(EMPTY_JSON, Map.class); |
| assertEquals(0, map.size()); |
| |
| bean = MAPPER.readValue(EMPTY_JSON, MapBean.class); |
| assertEquals(0, bean.map.size()); |
| } |
| |
| public void testCreatorWithDupNames() throws Exception |
| { |
| try { |
| MAPPER.readValue("{\"bar\":\"x\"}", BrokenCreatorBean.class); |
| fail("Should have caught duplicate creator parameters"); |
| } catch (JsonMappingException e) { |
| verifyException(e, "duplicate creator property \"bar\""); |
| } |
| } |
| |
| public void testCreatorMultipleArgumentWithoutAnnotation() throws Exception { |
| AutoDetectConstructorBean value = MAPPER.readValue("{\"bar\":\"bar\",\"foo\":\"foo\"}", |
| AutoDetectConstructorBean.class); |
| assertEquals("bar", value.bar); |
| assertEquals("foo", value.foo); |
| } |
| |
| public void testIgnoredSingleArgCtor() throws Exception |
| { |
| try { |
| MAPPER.readValue(quote("abc"), IgnoredCtor.class); |
| fail("Should have caught missing constructor problem"); |
| } catch (JsonMappingException e) { |
| verifyException(e, "no single-String constructor/factory method"); |
| } |
| } |
| |
| public void testAbstractFactory() throws Exception |
| { |
| AbstractBase bean = MAPPER.readValue("{\"a\":3}", AbstractBase.class); |
| assertNotNull(bean); |
| AbstractBaseImpl impl = (AbstractBaseImpl) bean; |
| assertEquals(1, impl.props.size()); |
| assertEquals(Integer.valueOf(3), impl.props.get("a")); |
| } |
| |
| public void testCreatorProperties() throws Exception |
| { |
| Issue700Bean value = MAPPER.readValue("{ \"item\" : \"foo\" }", Issue700Bean.class); |
| assertNotNull(value); |
| } |
| } |