diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x
index 2a2d3cefb..07ec43080 100644
--- a/release-notes/VERSION-2.x
+++ b/release-notes/VERSION-2.x
@@ -8,6 +8,8 @@ Project: jackson-dataformat-xml
#242: Deserialization of class inheritance depends on attributes order
(reported by Victor K)
+#325: Problem with '$' in polymorphic type id names when "as class",
+ "wrapper object", inner class
#326: Force namespace-repairing on `XMLOutputFactory` instances
#354: Support mapping `xsi:nul` marked elements as `null`s (`JsonToken.VALUE_NULL`)
diff --git a/src/main/java/com/fasterxml/jackson/dataformat/xml/DefaultingXmlTypeResolverBuilder.java b/src/main/java/com/fasterxml/jackson/dataformat/xml/DefaultingXmlTypeResolverBuilder.java
new file mode 100644
index 000000000..a545728e7
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/dataformat/xml/DefaultingXmlTypeResolverBuilder.java
@@ -0,0 +1,83 @@
+package com.fasterxml.jackson.dataformat.xml;
+
+import java.util.Collection;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.cfg.MapperConfig;
+import com.fasterxml.jackson.databind.jsontype.NamedType;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
+import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
+import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
+
+import com.fasterxml.jackson.dataformat.xml.util.StaxUtil;
+
+/**
+ * Sub-class of {@code StdTypeResolverBuilder} specifically used with
+ * Default Typing.
+ *
+ * Composition/sub-classing gets quite tricky here: ideally we would just
+ * extend {@link XmlTypeResolverBuilder} but unfortunately inheritance hierarchy
+ * does not allow this.
+ *
+ * @since 2.10
+ */
+public class DefaultingXmlTypeResolverBuilder
+ extends ObjectMapper.DefaultTypeResolverBuilder
+ implements java.io.Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ public DefaultingXmlTypeResolverBuilder(DefaultTyping t, PolymorphicTypeValidator ptv) {
+ super(t, ptv);
+ }
+
+ /*
+ /**********************************************************************
+ /* Methods copied from `XmlTypeResolverBuilder`
+ /**********************************************************************
+ */
+
+ @Override
+ public StdTypeResolverBuilder init(JsonTypeInfo.Id idType, TypeIdResolver idRes)
+ {
+ super.init(idType, idRes);
+ if (_typeProperty != null) {
+ _typeProperty = StaxUtil.sanitizeXmlTypeName(_typeProperty);
+ }
+ return this;
+ }
+
+ @Override
+ public StdTypeResolverBuilder typeProperty(String typeIdPropName)
+ {
+ // ok to have null/empty; will restore to use defaults
+ if (typeIdPropName == null || typeIdPropName.length() == 0) {
+ typeIdPropName = _idType.getDefaultPropertyName();
+ }
+ _typeProperty = StaxUtil.sanitizeXmlTypeName(typeIdPropName);
+ return this;
+ }
+
+ @Override
+ protected TypeIdResolver idResolver(MapperConfig> config,
+ JavaType baseType, PolymorphicTypeValidator subtypeValidator,
+ Collection subtypes, boolean forSer, boolean forDeser)
+ {
+ if (_customIdResolver != null) {
+ return _customIdResolver;
+ }
+ // Only override handlers of class, minimal class; name is good as is
+ switch (_idType) {
+ case CLASS:
+ return new XmlTypeResolverBuilder.XmlClassNameIdResolver(baseType, config.getTypeFactory(),
+ subTypeValidator(config));
+ case MINIMAL_CLASS:
+ return new XmlTypeResolverBuilder.XmlMinimalClassNameIdResolver(baseType, config.getTypeFactory(),
+ subTypeValidator(config));
+ default:
+ }
+ return super.idResolver(config, baseType, subtypeValidator, subtypes, forSer, forDeser);
+ }
+}
diff --git a/src/main/java/com/fasterxml/jackson/dataformat/xml/XmlMapper.java b/src/main/java/com/fasterxml/jackson/dataformat/xml/XmlMapper.java
index a5f42a93b..6e1a58a47 100644
--- a/src/main/java/com/fasterxml/jackson/dataformat/xml/XmlMapper.java
+++ b/src/main/java/com/fasterxml/jackson/dataformat/xml/XmlMapper.java
@@ -212,9 +212,7 @@ public Version version() {
@Override // since 2.10
protected TypeResolverBuilder> _constructDefaultTypeResolverBuilder(DefaultTyping applicability,
PolymorphicTypeValidator ptv) {
-// return DefaultTypeResolverBuilder.cosntruct(applicability, ptv);
- // just a stub for now
- return super._constructDefaultTypeResolverBuilder(applicability, ptv);
+ return new DefaultingXmlTypeResolverBuilder(applicability, ptv);
}
/*
diff --git a/src/main/java/com/fasterxml/jackson/dataformat/xml/XmlTypeResolverBuilder.java b/src/main/java/com/fasterxml/jackson/dataformat/xml/XmlTypeResolverBuilder.java
index e23f14f14..6f7f21aea 100644
--- a/src/main/java/com/fasterxml/jackson/dataformat/xml/XmlTypeResolverBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/dataformat/xml/XmlTypeResolverBuilder.java
@@ -4,6 +4,7 @@
import java.util.Collection;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.jsontype.NamedType;
@@ -13,6 +14,7 @@
import com.fasterxml.jackson.databind.jsontype.impl.MinimalClassNameIdResolver;
import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
import com.fasterxml.jackson.databind.type.TypeFactory;
+
import com.fasterxml.jackson.dataformat.xml.util.StaxUtil;
/**
@@ -25,6 +27,7 @@ public class XmlTypeResolverBuilder extends StdTypeResolverBuilder
@Override
public StdTypeResolverBuilder init(JsonTypeInfo.Id idType, TypeIdResolver idRes)
{
+
super.init(idType, idRes);
if (_typeProperty != null) {
_typeProperty = StaxUtil.sanitizeXmlTypeName(_typeProperty);
diff --git a/src/test/java/com/fasterxml/jackson/dataformat/xml/failing/DefaultTyping325Test.java b/src/test/java/com/fasterxml/jackson/dataformat/xml/failing/DefaultTyping325Test.java
index 3f78b0821..dc8504249 100644
--- a/src/test/java/com/fasterxml/jackson/dataformat/xml/failing/DefaultTyping325Test.java
+++ b/src/test/java/com/fasterxml/jackson/dataformat/xml/failing/DefaultTyping325Test.java
@@ -1,37 +1,36 @@
package com.fasterxml.jackson.dataformat.xml.failing;
import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
+
import com.fasterxml.jackson.dataformat.xml.XmlTestBase;
import com.fasterxml.jackson.dataformat.xml.testutil.NoCheckSubTypeValidator;
public class DefaultTyping325Test extends XmlTestBase
{
- static class Simple {
- protected List list;
+ static class Simple325 {
+ protected String[] list;
- public List getList( ) { return list; }
- public void setList(List l) { list = l; }
+ public String[] getList( ) { return list; }
+ public void setList(String[] l) { list = l; }
}
- public void testCanSerialize() throws IOException
+ // [dataformat-xml#325]
+ public void testDefaultTypingWithInnerClass() throws IOException
{
ObjectMapper mapper = mapperBuilder()
.activateDefaultTyping(NoCheckSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_OBJECT)
.build();
- // construct test object
- Simple s = new Simple();
- s.setList(Arrays.asList("foo", "bar"));
+ Simple325 s = new Simple325();
+ s.setList(new String[] { "foo", "bar" });
String doc = mapper.writeValueAsString(s);
- Simple result = mapper.readValue(doc, Simple.class);
+ Simple325 result = mapper.readValue(doc, Simple325.class);
assertNotNull(result.list);
- assertEquals(2, result.list.size());
+ assertEquals(2, result.list.length);
}
}
diff --git a/src/test/java/com/fasterxml/jackson/dataformat/xml/testutil/NoCheckSubTypeValidator.java b/src/test/java/com/fasterxml/jackson/dataformat/xml/testutil/NoCheckSubTypeValidator.java
index b90f1de7d..ff66a424c 100644
--- a/src/test/java/com/fasterxml/jackson/dataformat/xml/testutil/NoCheckSubTypeValidator.java
+++ b/src/test/java/com/fasterxml/jackson/dataformat/xml/testutil/NoCheckSubTypeValidator.java
@@ -19,4 +19,21 @@ public final class NoCheckSubTypeValidator
public Validity validateBaseType(MapperConfig> c, JavaType baseType) {
return Validity.ALLOWED;
}
-}
\ No newline at end of file
+
+ // Important! With Default Typing, "validateBaseType()" won't necessarily
+ // be called, at least for root type, so need more than above method:
+
+ @Override
+ public Validity validateSubClassName(MapperConfig> config,
+ JavaType baseType, String subClassName) {
+ return Validity.ALLOWED;
+ }
+
+ /*
+ @Override
+ public Validity validateSubType(MapperConfig> config, JavaType baseType,
+ JavaType subType) {
+ return Validity.ALLOWED;
+ }
+ */
+}