-
-
Notifications
You must be signed in to change notification settings - Fork 220
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added support for @JsonUnwrapped annotation. Fixes #83.
- Loading branch information
Pascal Gélinas
committed
Jan 30, 2014
1 parent
ab84ac9
commit f64d69d
Showing
4 changed files
with
285 additions
and
3 deletions.
There are no files selected for viewing
144 changes: 144 additions & 0 deletions
144
src/main/java/com/fasterxml/jackson/dataformat/xml/ser/UnwrappingXmlBeanSerializer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
package com.fasterxml.jackson.dataformat.xml.ser; | ||
|
||
import java.io.IOException; | ||
|
||
import com.fasterxml.jackson.core.*; | ||
import com.fasterxml.jackson.databind.*; | ||
import com.fasterxml.jackson.databind.ser.*; | ||
import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter; | ||
import com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer; | ||
import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase; | ||
import com.fasterxml.jackson.databind.util.NameTransformer; | ||
|
||
/** | ||
* Copy of {@link UnwrappingBeanSerializer} required to extend | ||
* {@link XmlBeanSerializerBase} for XML-specific handling. | ||
* | ||
* @author Pascal Gélinas | ||
* | ||
*/ | ||
public class UnwrappingXmlBeanSerializer extends XmlBeanSerializerBase { | ||
/** | ||
* Transformer used to add prefix and/or suffix for properties of unwrapped | ||
* POJO. | ||
*/ | ||
protected final NameTransformer _nameTransformer; | ||
|
||
/* | ||
/********************************************************** | ||
/* Life-cycle: constructors | ||
/********************************************************** | ||
*/ | ||
|
||
/** | ||
* Constructor used for creating unwrapping instance of a standard | ||
* <code>BeanSerializer</code> | ||
*/ | ||
public UnwrappingXmlBeanSerializer(XmlBeanSerializerBase src, NameTransformer transformer) | ||
{ | ||
super(src, transformer); | ||
_nameTransformer = transformer; | ||
} | ||
|
||
public UnwrappingXmlBeanSerializer(UnwrappingXmlBeanSerializer src, ObjectIdWriter objectIdWriter) | ||
{ | ||
super(src, objectIdWriter); | ||
_nameTransformer = src._nameTransformer; | ||
} | ||
|
||
public UnwrappingXmlBeanSerializer(UnwrappingXmlBeanSerializer src, ObjectIdWriter objectIdWriter, Object filterId) | ||
{ | ||
super(src, objectIdWriter, filterId); | ||
_nameTransformer = src._nameTransformer; | ||
} | ||
|
||
protected UnwrappingXmlBeanSerializer(UnwrappingXmlBeanSerializer src, String[] toIgnore) | ||
{ | ||
super(src, toIgnore); | ||
_nameTransformer = src._nameTransformer; | ||
} | ||
|
||
/* | ||
/********************************************************** | ||
/* Life-cycle: factory methods, fluent factories | ||
/********************************************************** | ||
*/ | ||
|
||
@Override | ||
public JsonSerializer<Object> unwrappingSerializer(NameTransformer transformer) | ||
{ | ||
// !!! 23-Jan-2012, tatu: Should we chain transformers? | ||
return new UnwrappingXmlBeanSerializer(this, transformer); | ||
} | ||
|
||
@Override | ||
public boolean isUnwrappingSerializer() | ||
{ | ||
return true; // sure is | ||
} | ||
|
||
@Override | ||
public BeanSerializerBase withObjectIdWriter(ObjectIdWriter objectIdWriter) | ||
{ | ||
return new UnwrappingXmlBeanSerializer(this, objectIdWriter); | ||
} | ||
|
||
@Override | ||
protected BeanSerializerBase withFilterId(Object filterId) | ||
{ | ||
return new UnwrappingXmlBeanSerializer(this, _objectIdWriter, filterId); | ||
} | ||
|
||
@Override | ||
protected BeanSerializerBase withIgnorals(String[] toIgnore) | ||
{ | ||
return new UnwrappingXmlBeanSerializer(this, toIgnore); | ||
} | ||
|
||
/** | ||
* JSON Array output can not be done if unwrapping operation is requested; | ||
* so implementation will simply return 'this'. | ||
*/ | ||
@Override | ||
protected BeanSerializerBase asArraySerializer() | ||
{ | ||
return this; | ||
} | ||
|
||
/* | ||
/********************************************************** | ||
/* JsonSerializer implementation that differs between impls | ||
/********************************************************** | ||
*/ | ||
|
||
/** | ||
* Main serialization method that will delegate actual output to configured | ||
* {@link BeanPropertyWriter} instances. | ||
*/ | ||
@Override | ||
public final void serialize(Object bean, JsonGenerator jgen, SerializerProvider provider) | ||
throws IOException, JsonGenerationException | ||
{ | ||
if (_objectIdWriter != null) { | ||
_serializeWithObjectId(bean, jgen, provider, false); | ||
return; | ||
} | ||
if (_propertyFilterId != null) { | ||
serializeFieldsFiltered(bean, jgen, provider); | ||
} else { | ||
serializeFields(bean, jgen, provider); | ||
} | ||
} | ||
|
||
/* | ||
/********************************************************** | ||
/* Standard methods | ||
/********************************************************** | ||
*/ | ||
|
||
@Override | ||
public String toString() | ||
{ | ||
return "UnwrappingXmlBeanSerializer for " + handledType().getName(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
136 changes: 136 additions & 0 deletions
136
src/test/java/com/fasterxml/jackson/dataformat/xml/TestUnwrappingWithXML.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package com.fasterxml.jackson.dataformat.xml; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
import org.junit.Test; | ||
|
||
import com.fasterxml.jackson.annotation.JsonPropertyOrder; | ||
import com.fasterxml.jackson.annotation.JsonUnwrapped; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; | ||
|
||
// for #12 | ||
public class TestUnwrappingWithXML extends XmlTestBase | ||
{ | ||
@JsonPropertyOrder({"x", "y"}) | ||
final static class Location { | ||
public int x; | ||
public int y; | ||
|
||
public Location() { } | ||
public Location(int x, int y) { | ||
this.x = x; | ||
this.y = y; | ||
} | ||
} | ||
|
||
// IMPORTANT: ordering DOES matter here | ||
@JsonPropertyOrder({ "name", "location" }) | ||
static class Unwrapping { | ||
public String name; | ||
@JsonUnwrapped(prefix="loc.") | ||
public Location location; | ||
|
||
public Unwrapping() { } | ||
public Unwrapping(String str, int x, int y) { | ||
name = str; | ||
location = new Location(x, y); | ||
} | ||
} | ||
|
||
static class UnwrappingWithAttributes{ | ||
@JacksonXmlProperty(isAttribute=true) | ||
public String name; | ||
@JacksonXmlProperty(isAttribute=true) | ||
@JsonUnwrapped(prefix="loc.") | ||
public Location location; | ||
|
||
public UnwrappingWithAttributes() { } | ||
public UnwrappingWithAttributes(String str, int x, int y) { | ||
name = str; | ||
location = new Location(x, y); | ||
} | ||
} | ||
|
||
static class UnwrappingSubWithAttributes{ | ||
@JacksonXmlProperty(isAttribute=true) | ||
public String name; | ||
@JsonUnwrapped(prefix="loc.") | ||
public LocationWithAttributes location; | ||
|
||
public UnwrappingSubWithAttributes() { } | ||
public UnwrappingSubWithAttributes(String str, int x, int y) { | ||
name = str; | ||
location = new LocationWithAttributes(x, y); | ||
} | ||
} | ||
|
||
@JsonPropertyOrder({"x", "y"}) | ||
final static class LocationWithAttributes { | ||
@JacksonXmlProperty(isAttribute=true) | ||
public int x; | ||
@JacksonXmlProperty(isAttribute=true) | ||
public int y; | ||
|
||
public LocationWithAttributes() { } | ||
public LocationWithAttributes(int x, int y) { | ||
this.x = x; | ||
this.y = y; | ||
} | ||
} | ||
|
||
/* | ||
/********************************************************** | ||
/* Tests | ||
/********************************************************** | ||
*/ | ||
|
||
/** | ||
* Simple test to verify that explicit schema mapping works fine | ||
* with unwrapped entities | ||
*/ | ||
public void testSimpleUnwrappingRoundtrip() | ||
throws Exception | ||
{ | ||
final String XML = "<Unwrapping><name>Joe</name><loc.x>15</loc.x><loc.y>27</loc.y></Unwrapping>"; | ||
ObjectMapper mapper = xmlMapper(false); | ||
Unwrapping wrapper = mapper.reader(Unwrapping.class).readValue(XML); | ||
assertNotNull(wrapper); | ||
assertNotNull(wrapper.location); | ||
assertEquals(15, wrapper.location.x); | ||
assertEquals(27, wrapper.location.y); | ||
|
||
// should also write out the same way | ||
assertEquals(XML, mapper.writerWithType(Unwrapping.class).writeValueAsString(wrapper)); | ||
} | ||
|
||
public void testUnwrappingWithAttribute() | ||
throws Exception | ||
{ | ||
final String XML = "<UnwrappingWithAttributes name=\"Joe\" loc.x=\"15\" loc.y=\"27\"/>"; | ||
ObjectMapper mapper = xmlMapper(false); | ||
UnwrappingWithAttributes wrapper = mapper.reader(UnwrappingWithAttributes.class).readValue(XML); | ||
assertNotNull(wrapper); | ||
assertNotNull(wrapper.location); | ||
assertEquals(15, wrapper.location.x); | ||
assertEquals(27, wrapper.location.y); | ||
|
||
// should also write out the same way | ||
assertEquals(XML, mapper.writerWithType(UnwrappingWithAttributes.class).writeValueAsString(wrapper)); | ||
} | ||
|
||
public void testUnwrappingSubWithAttribute() | ||
throws Exception | ||
{ | ||
final String XML = "<UnwrappingSubWithAttributes name=\"Joe\" loc.x=\"15\" loc.y=\"27\"/>"; | ||
ObjectMapper mapper = xmlMapper(false); | ||
UnwrappingSubWithAttributes wrapper = mapper.reader(UnwrappingSubWithAttributes.class).readValue(XML); | ||
assertNotNull(wrapper); | ||
assertNotNull(wrapper.location); | ||
assertEquals(15, wrapper.location.x); | ||
assertEquals(27, wrapper.location.y); | ||
|
||
// should also write out the same way | ||
assertEquals(XML, mapper.writerWithType(UnwrappingSubWithAttributes.class).writeValueAsString(wrapper)); | ||
} | ||
} |