diff --git a/src/test/java/com/fasterxml/jackson/failing/Jackson212MissingConstructorJavaTest.java b/src/test/java/com/fasterxml/jackson/failing/Jackson212MissingConstructorJavaTest.java new file mode 100644 index 0000000..69fe092 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/failing/Jackson212MissingConstructorJavaTest.java @@ -0,0 +1,122 @@ +package com.fasterxml.jackson.failing; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRootName; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.fasterxml.jackson.integtest.BaseTest; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +/** + * @see Jackson212MissingConstructorTest + * @see jackson-module-kotlin issue 396 + */ +public class Jackson212MissingConstructorJavaTest extends BaseTest { + + interface Problem { + String DEFAULT_TYPE = "about:blank"; + int DEFAULT_STATUS = 500; + + String getType(); + + int getStatus(); + } + + static class DefaultProblem implements Problem { + private final String type; + private final int status; + + /** + * This is required to workaround Jackson's missing support for static + * {@link JsonCreator}s in mix-ins. That is, we need to define the + * creator on a constructor in the mix-in that is matching with a + * constructor here too. + * + * @see jackson-databind issue 1820 + */ + DefaultProblem(String type, Integer status) { + this.type = type != null ? type : Problem.DEFAULT_TYPE; + this.status = status != null ? status : Problem.DEFAULT_STATUS; + } + + @Override + public String getType() { + return type; + } + + @Override + public int getStatus() { + return status; + } + } + + @JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXISTING_PROPERTY, + property = "type", + defaultImpl = DefaultProblem.class, + visible = true) + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonRootName("problem") + interface ProblemMixIn extends Problem { + + @Override + @JsonProperty("type") + String getType(); + + @Override + @JsonProperty("status") + int getStatus(); + } + + abstract static class DefaultProblemMixIn extends DefaultProblem { + + @JsonCreator + DefaultProblemMixIn(@JsonProperty("type") String type, @JsonProperty("status") Integer status) { + super(type, status); + throw new IllegalStateException( + "mix-in constructor is there only for extracting the JSON mapping, " + + "it should not have been called"); + } + } + + static class ProblemModule extends SimpleModule { + + @Override + public void setupModule(SetupContext context) { + super.setupModule(context); + registerMixIns(context); + } + + private static void registerMixIns(SetupContext context) { + context.setMixInAnnotations(DefaultProblem.class, DefaultProblemMixIn.class); + context.setMixInAnnotations(Problem.class, ProblemMixIn.class); + } + } + + private static final ProblemModule MODULE = new ProblemModule(); + + private static final ObjectMapper JSON_MAPPER = new ObjectMapper().registerModule(MODULE); + + private static final XmlMapper XML_MAPPER = (XmlMapper) new XmlMapper().registerModule(MODULE); + + public void testEmptyProblemJsonDeserialization() throws IOException { + byte[] problemJsonBytes = "{}".getBytes(StandardCharsets.UTF_8); + Problem problem = JSON_MAPPER.readValue(problemJsonBytes, Problem.class); + assertEquals(Problem.DEFAULT_TYPE, problem.getType()); + assertEquals(Problem.DEFAULT_STATUS, problem.getStatus()); + } + + public void testEmptyProblemXmlDeserialization() throws IOException { + byte[] problemXmlBytes = "".getBytes(StandardCharsets.UTF_8); + Problem problem = XML_MAPPER.readValue(problemXmlBytes, Problem.class); + assertEquals(Problem.DEFAULT_TYPE, problem.getType()); + assertEquals(Problem.DEFAULT_STATUS, problem.getStatus()); + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/fasterxml/jackson/failing/Jackson212MissingConstructorTest.kt b/src/test/kotlin/com/fasterxml/jackson/failing/Jackson212MissingConstructorTest.kt index f515158..69a66c5 100644 --- a/src/test/kotlin/com/fasterxml/jackson/failing/Jackson212MissingConstructorTest.kt +++ b/src/test/kotlin/com/fasterxml/jackson/failing/Jackson212MissingConstructorTest.kt @@ -10,8 +10,9 @@ import javax.xml.stream.XMLInputFactory class Jackson212MissingConstructorTest : BaseTest() { /** - * Succeeds in Jackson 2.11.x, but fails in Jackson 2.12.0 - * See https://github.com/FasterXML/jackson-module-kotlin/issues/396 + * Succeeds in Jackson 2.11.x, but fails in Jackson 2.12.x + * + * @see jackson-databind issue 396 */ fun testMissingConstructor() {