package com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; public class ImplicitNameMatch792Test extends BaseMapTest { // Simple introspector that gives generated "ctorN" names for constructor // parameters static class ConstructorNameAI extends JacksonAnnotationIntrospector { private static final long serialVersionUID = 1L; @Override public String findImplicitPropertyName(AnnotatedMember member) { if (member instanceof AnnotatedParameter) { return String.format("ctor%d", ((AnnotatedParameter) member).getIndex()); } return super.findImplicitPropertyName(member); } } @JsonPropertyOrder({ "first" ,"second", "other" }) static class Issue792Bean { String value; public Issue792Bean(@JsonProperty("first") String a, @JsonProperty("second") String b) { value = a; // ignore second arg } public String getCtor0() { return value; } public int getOther() { return 3; } } static class Bean2 { int x = 3; @JsonProperty("stuff") private void setValue(int i) { x = i; } public int getValue() { return x; } } static class ReadWriteBean { private int value; private ReadWriteBean(@JsonProperty(value="value", access=JsonProperty.Access.READ_WRITE) int v) { value = v; } public int testValue() { return value; } // Let's also add setter to ensure conflict resolution works public void setValue(int v) { throw new RuntimeException("Should have used constructor for 'value' not setter"); } } // Bean that should only serialize 'value', but deserialize both static class PasswordBean { @JsonProperty(access=JsonProperty.Access.WRITE_ONLY) private String password; private int value; public int getValue() { return value; } public String getPassword() { return password; } public String asString() { return String.format("[password='%s',value=%d]", password, value); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = sharedMapper(); public void testBindingOfImplicitCreatorNames() throws Exception { ObjectMapper m = new ObjectMapper(); m.setAnnotationIntrospector(new ConstructorNameAI()); String json = m.writeValueAsString(new Issue792Bean("a", "b")); assertEquals(aposToQuotes("{'first':'a','other':3}"), json); } public void testImplicitWithSetterGetter() throws Exception { String json = MAPPER.writeValueAsString(new Bean2()); assertEquals(aposToQuotes("{'stuff':3}"), json); } public void testReadWriteWithPrivateField() throws Exception { String json = MAPPER.writeValueAsString(new ReadWriteBean(3)); assertEquals("{\"value\":3}", json); } public void testWriteOnly() throws Exception { PasswordBean bean = MAPPER.readValue(aposToQuotes("{'value':7,'password':'foo'}"), PasswordBean.class); assertEquals("[password='foo',value=7]", bean.asString()); String json = MAPPER.writeValueAsString(bean); assertEquals("{\"value\":7}", json); } }