RecordCreatorsTest.java
package tools.jackson.databind.records;
import java.util.*;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
import tools.jackson.databind.*;
import tools.jackson.databind.exc.UnrecognizedPropertyException;
import tools.jackson.databind.testutil.DatabindTestUtil;
import static org.junit.jupiter.api.Assertions.*;
public class RecordCreatorsTest extends DatabindTestUtil
{
record RecordWithCanonicalCtorOverride(int id, String name) {
public RecordWithCanonicalCtorOverride(int id, String name) {
this.id = id;
this.name = "name";
}
}
record RecordWithAltCtor(int id, String name) {
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public RecordWithAltCtor(@JsonProperty("id") int id) {
this(id, "name2");
}
}
// [databind#2980]
record RecordWithDelegation(String value) {
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public RecordWithDelegation(String value) {
this.value = "del:"+value;
}
@JsonValue
public String getValue() {
return "val:"+value;
}
public String accessValueForTest() { return value; }
}
// [databind#4452]
public record PlainTestObject(
@JsonProperty("strField") String testFieldName,
@JsonProperty("intField") Integer testOtherField
) { }
public record CreatorTestObject(
String testFieldName,
Integer testOtherField
) {
@JsonCreator
public CreatorTestObject(
@JsonProperty("strField") String testFieldName,
@JsonProperty("someOtherIntField") Integer testOtherIntField,
@JsonProperty("intField") Integer testOtherField)
{
this(testFieldName, testOtherField + testOtherIntField);
}
}
// [databind#4724]
public record Something(String value) {
public Something {
if (value == null || value.isEmpty()) {
throw new IllegalArgumentException("Value cannot be null or empty");
}
}
// should be considered Delegating due to @JsonValue later on
@JsonCreator
public static Something of(String value) {
if (value.isEmpty()) {
return null;
}
return new Something(value);
}
@Override
@JsonValue
public String toString() {
return value;
}
}
private final ObjectMapper MAPPER = jsonMapperBuilder().enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).build();
/*
/**********************************************************************
/* Test methods, alternate constructors
/**********************************************************************
*/
@Test
public void testDeserializeWithCanonicalCtorOverride() throws Exception {
RecordWithCanonicalCtorOverride value = MAPPER.readValue("{\"id\":123,\"name\":\"Bob\"}",
RecordWithCanonicalCtorOverride.class);
assertEquals(123, value.id());
assertEquals("name", value.name());
}
@Test
public void testDeserializeWithAltCtor() throws Exception {
RecordWithAltCtor value = MAPPER.readValue("{\"id\":2812}",
RecordWithAltCtor.class);
assertEquals(2812, value.id());
assertEquals("name2", value.name());
// "Implicit" canonical constructor can no longer be used when there's explicit constructor
try {
MAPPER.readValue("{\"id\":2812,\"name\":\"Bob\"}",
RecordWithAltCtor.class);
fail("should not pass");
} catch (UnrecognizedPropertyException e) {
verifyException(e, "Unrecognized");
verifyException(e, "\"name\"");
verifyException(e, "RecordWithAltCtor");
}
}
// [databind#2980]
@Test
public void testDeserializeWithDelegatingCtor() throws Exception {
RecordWithDelegation value = MAPPER.readValue(q("foobar"),
RecordWithDelegation.class);
assertEquals("del:foobar", value.accessValueForTest());
assertEquals(q("val:del:foobar"), MAPPER.writeValueAsString(value));
}
/*
/**********************************************************************
/* Test methods, @JsonProperty on @JsonCreator [databind#4452]
/**********************************************************************
*/
// [databind#4452]
@Test
public void testCreatorSerializationWithJsonProperty4452Plain() throws Exception
{
String result = MAPPER.writeValueAsString(new PlainTestObject("test", 1));
assertEquals(a2q("{'strField':'test','intField':1}"), result);
}
@Test
public void testCreatorSerializationWithJsonProperty4452WithCreator() throws Exception
{
String json = MAPPER.writeValueAsString(new CreatorTestObject("test", 2, 1));
@SuppressWarnings("unchecked")
Map<String, Object> asMap = (Map<String, Object>) MAPPER.readValue(json, Map.class);
assertEquals(new HashSet<>(Arrays.asList("intField", "strField")), asMap.keySet());
}
/*
/**********************************************************************
/* Test methods, @JsonCreator with @JsonValue [databind#4724]
/**********************************************************************
*/
// [databind#4724]
@Test
void testDeserializeWithCreatorAndJsonValue4724() throws Exception {
newJsonMapper().readValue("\"\"", Something.class);
}
}