Skip to content

Commit 7c684f6

Browse files
authored
Adds test to reproduce the no default no-arg ctor regression in #491. (#492)
Co-authored-by: Volkan Yazıcı <[email protected]>
1 parent 262ea19 commit 7c684f6

File tree

1 file changed

+137
-0
lines changed

1 file changed

+137
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package com.fasterxml.jackson.dataformat.xml.failing;
2+
3+
import com.fasterxml.jackson.annotation.*;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import com.fasterxml.jackson.databind.module.SimpleModule;
6+
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
7+
import com.fasterxml.jackson.dataformat.xml.XmlTestBase;
8+
9+
import java.io.IOException;
10+
import java.nio.charset.StandardCharsets;
11+
12+
/**
13+
* Reproduces <i>no default no-arg ctor found</i> deserialization regression introduced to {@link XmlMapper} in 2.12.0.
14+
*
15+
* @see <a href="https://github.com/FasterXML/jackson-dataformat-xml/issues/491">jackson-dataformat-xml issue 491</a>
16+
*/
17+
public class Issue491NoArgCtorDeserRegressionTest extends XmlTestBase {
18+
19+
interface Problem {
20+
21+
String DEFAULT_TYPE = "about:blank";
22+
23+
int DEFAULT_STATUS = 500;
24+
25+
String getType();
26+
27+
int getStatus();
28+
29+
}
30+
31+
static class DefaultProblem implements Problem {
32+
33+
private final String type;
34+
35+
private final int status;
36+
37+
/**
38+
* This is required to workaround Jackson's missing support for static
39+
* {@link JsonCreator}s in mix-ins. That is, we need to define the
40+
* creator on a constructor in the mix-in that is matching with a
41+
* constructor here too.
42+
*
43+
* @see <a href="https://github.com/FasterXML/jackson-databind/issues/1820">jackson-databind issue 1820</a>
44+
*/
45+
DefaultProblem(String type, Integer status) {
46+
this.type = type != null ? type : Problem.DEFAULT_TYPE;
47+
this.status = status != null ? status : Problem.DEFAULT_STATUS;
48+
}
49+
50+
@Override
51+
public String getType() {
52+
return type;
53+
}
54+
55+
@Override
56+
public int getStatus() {
57+
return status;
58+
}
59+
60+
}
61+
62+
@JsonTypeInfo(
63+
use = JsonTypeInfo.Id.NAME,
64+
include = JsonTypeInfo.As.EXISTING_PROPERTY,
65+
property = "type",
66+
defaultImpl = DefaultProblem.class,
67+
visible = true)
68+
@JsonInclude(JsonInclude.Include.NON_EMPTY)
69+
@JsonRootName("problem")
70+
interface ProblemMixIn extends Problem {
71+
72+
@Override
73+
@JsonProperty("type")
74+
String getType();
75+
76+
@Override
77+
@JsonProperty("status")
78+
int getStatus();
79+
80+
}
81+
82+
abstract static class DefaultProblemMixIn extends DefaultProblem {
83+
84+
@JsonCreator
85+
DefaultProblemMixIn(
86+
@JsonProperty("type") String type,
87+
@JsonProperty("status") Integer status) {
88+
super(type, status);
89+
throw new IllegalStateException(
90+
"mix-in constructor is there only for extracting the JSON mapping, " +
91+
"it should not have been called");
92+
}
93+
94+
}
95+
96+
static class ProblemModule extends SimpleModule {
97+
98+
@Override
99+
public void setupModule(SetupContext context) {
100+
super.setupModule(context);
101+
registerMixIns(context);
102+
}
103+
104+
private static void registerMixIns(SetupContext context) {
105+
context.setMixInAnnotations(DefaultProblem.class, DefaultProblemMixIn.class);
106+
context.setMixInAnnotations(Problem.class, ProblemMixIn.class);
107+
}
108+
109+
}
110+
111+
private static final ProblemModule MODULE = new ProblemModule();
112+
113+
private static final ObjectMapper JSON_MAPPER = new ObjectMapper().registerModule(MODULE);
114+
115+
private static final XmlMapper XML_MAPPER = (XmlMapper) new XmlMapper().registerModule(MODULE);
116+
117+
/**
118+
* Passes on 2.11.4 and 2.12.{0..4}.
119+
*/
120+
public void test_empty_Problem_JSON_deserialization() throws IOException {
121+
byte[] problemJsonBytes = "{}".getBytes(StandardCharsets.UTF_8);
122+
Problem problem = JSON_MAPPER.readValue(problemJsonBytes, Problem.class);
123+
assertEquals(Problem.DEFAULT_TYPE, problem.getType());
124+
assertEquals(Problem.DEFAULT_STATUS, problem.getStatus());
125+
}
126+
127+
/**
128+
* Passes on 2.11.4, but fails on 2.12.{0..4}.
129+
*/
130+
public void test_empty_Problem_XML_deserialization() throws IOException {
131+
byte[] problemXmlBytes = "<problem/>".getBytes(StandardCharsets.UTF_8);
132+
Problem problem = XML_MAPPER.readValue(problemXmlBytes, Problem.class);
133+
assertEquals(Problem.DEFAULT_TYPE, problem.getType());
134+
assertEquals(Problem.DEFAULT_STATUS, problem.getStatus());
135+
}
136+
137+
}

0 commit comments

Comments
 (0)