Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions release-notes/CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ Severin Kistler (@kistlers)
`java.util.Map`) fails
(3.2.0)

Alex Olson (@alexkolson)
* Reported #665: `@JacksonXmlProperty` appears to behave differently than
`@JsonProperty` when used on java records
(3.2.0)

Simon Cockx (@SimonCockx)
* Reported #762: Unwrapping lists does not work inside `@JsonUnwrapped`
(3.2.0)
Expand Down
6 changes: 5 additions & 1 deletion release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,15 @@ Version: 3.x (for earlier see VERSION-2.x)
`java.util.Map`) fails
(reported by Severin K)
(fix by Christopher M)
#665: `@JacksonXmlProperty` appears to behave differently than
`@JsonProperty` when used on java records
(reported by Alex O)
(fix by @cowtowncoder, w/ Claude code)
#735: Java Record with `@JacksonXmlText` stopped working with 2.18
(reported by @akastyka))
(fix by Christopher M)
#762: Unwrapping lists does not work inside `@JsonUnwrapped`
(reported by Simon C)
(reported by Simon C)
(fix by @cowtowncoder, w/ Claude code)
#767: Unwrapped lists cannot be deserialized when using
`JsonTypeInfo.As.EXISTING_PROPERTY`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class JacksonXmlAnnotationIntrospector
@SuppressWarnings("unchecked")
private final static Class<? extends Annotation>[] ANNOTATIONS_TO_INFER_XML_PROP =
(Class<? extends Annotation>[]) new Class<?>[] {
JacksonXmlText.class, JacksonXmlElementWrapper.class
JacksonXmlProperty.class, JacksonXmlText.class, JacksonXmlElementWrapper.class
};

/**
Expand Down Expand Up @@ -243,7 +243,13 @@ protected PropertyName _findXmlName(Annotated a)
{
JacksonXmlProperty pann = _findAnnotation(a, JacksonXmlProperty.class);
if (pann != null) {
return PropertyName.construct(pann.localName(), pann.namespace());
// [dataformat-xml#665]: empty localName should not produce an
// empty-string PropertyName (causes "Duplicate creator property"
// on records); return null so that the implicit name is used.
String localName = pann.localName();
if (localName != null && !localName.isEmpty()) {
return PropertyName.construct(localName, pann.namespace());
}
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package tools.jackson.dataformat.xml.deser.records;

import org.junit.jupiter.api.Test;

import tools.jackson.dataformat.xml.*;
import tools.jackson.dataformat.xml.annotation.JacksonXmlProperty;

import static org.junit.jupiter.api.Assertions.*;

// [dataformat-xml#665]: @JacksonXmlProperty without localName on records
// should not cause "Duplicate creator property" error
public class XmlRecordDeser665Test extends XmlTestUtil
{
// Bare @JacksonXmlProperty (no arguments) on a record — was failing
record SimpleRecord(@JacksonXmlProperty String name, String value) {}

// @JacksonXmlProperty(isAttribute=true) without localName — the main use case
record AttributeRecord(@JacksonXmlProperty(isAttribute = true) String id, String name) {}

private final XmlMapper MAPPER = newMapper();

@Test
public void testBareAnnotationOnRecord() throws Exception {
String xml = "<SimpleRecord><name>test</name><value>val</value></SimpleRecord>";
SimpleRecord result = MAPPER.readValue(xml, SimpleRecord.class);
assertEquals("test", result.name());
assertEquals("val", result.value());
}

@Test
public void testIsAttributeWithoutLocalNameOnRecord() throws Exception {
String xml = "<AttributeRecord id='123'><name>test</name></AttributeRecord>";
AttributeRecord result = MAPPER.readValue(xml, AttributeRecord.class);
assertEquals("123", result.id());
assertEquals("test", result.name());
}

// Verify serialization round-trip works too
@Test
public void testSerializationRoundTrip() throws Exception {
AttributeRecord original = new AttributeRecord("123", "test");
String xml = MAPPER.writeValueAsString(original);
AttributeRecord result = MAPPER.readValue(xml, AttributeRecord.class);
assertEquals(original.id(), result.id());
assertEquals(original.name(), result.name());
}
}