Skip to content

Commit

Permalink
Fix #325
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Sep 24, 2019
1 parent 2bc25e4 commit b5ae1e8
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 16 deletions.
2 changes: 2 additions & 0 deletions release-notes/VERSION-2.x
Expand Up @@ -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`)

Expand Down
@@ -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.
*<p>
* 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<NamedType> 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);
}
}
Expand Up @@ -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);
}

/*
Expand Down
Expand Up @@ -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;
Expand All @@ -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;

/**
Expand All @@ -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);
Expand Down
@@ -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<String> list;
static class Simple325 {
protected String[] list;

public List<String> getList( ) { return list; }
public void setList(List<String> 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);
}
}
Expand Up @@ -19,4 +19,21 @@ public final class NoCheckSubTypeValidator
public Validity validateBaseType(MapperConfig<?> c, JavaType baseType) {
return Validity.ALLOWED;
}
}

// 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;
}
*/
}

0 comments on commit b5ae1e8

Please sign in to comment.