Implement feature [Issue-11]
diff --git a/release-notes/VERSION b/release-notes/VERSION
index 6d629fc..e79d0f7 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -8,6 +8,11 @@
Fixes:
+Improvements:
+
+* [Issue-11]: Improve ObjectMapper.convertValue()/.treeToValue() to use
+ cast if possible
+
------------------------------------------------------------------------
=== History: ===
------------------------------------------------------------------------
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
index 1d6294e..d95b98f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
@@ -1665,11 +1665,16 @@
* objectMapper.convertValue(n, valueClass);
*</pre>
*/
+ @SuppressWarnings("unchecked")
@Override
public <T> T treeToValue(TreeNode n, Class<T> valueType)
throws JsonProcessingException
{
try {
+ // [Issue-11]: Simple cast when we just want to cast to, say, ObjectNode
+ if (n.getClass().isAssignableFrom(valueType)) {
+ return (T) n;
+ }
return readValue(treeAsTokens(n), valueType);
} catch (JsonProcessingException e) {
throw e;
@@ -2266,20 +2271,31 @@
public <T> T convertValue(Object fromValue, Class<T> toValueType)
throws IllegalArgumentException
{
+ // sanity check for null first:
+ if (fromValue == null) return null;
+ // also, as per [Issue-11], consider case for simple cast
+ if (fromValue.getClass().isAssignableFrom(toValueType)) {
+ return (T) fromValue;
+ }
return (T) _convert(fromValue, _typeFactory.constructType(toValueType));
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public <T> T convertValue(Object fromValue, TypeReference toValueTypeRef)
+ public <T> T convertValue(Object fromValue, TypeReference<?> toValueTypeRef)
throws IllegalArgumentException
{
- return (T) _convert(fromValue, _typeFactory.constructType(toValueTypeRef));
+ return convertValue(fromValue, _typeFactory.constructType(toValueTypeRef));
}
@SuppressWarnings("unchecked")
public <T> T convertValue(Object fromValue, JavaType toValueType)
throws IllegalArgumentException
{
+ // sanity check for null first:
+ if (fromValue == null) return null;
+ // also, as per [Issue-11], consider case for simple cast
+ if (fromValue.getClass().isAssignableFrom(toValueType.getRawClass())) {
+ return (T) fromValue;
+ }
return (T) _convert(fromValue, toValueType);
}
@@ -2293,9 +2309,7 @@
*/
protected Object _convert(Object fromValue, JavaType toValueType)
throws IllegalArgumentException
- {
- // sanity check for null first:
- if (fromValue == null) return null;
+ {
/* Then use TokenBuffer, which is a JsonGenerator:
* (see [JACKSON-175])
*/
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java b/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java
index 85fcc67..bb5ddbf 100644
--- a/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java
@@ -2,12 +2,14 @@
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.node.ObjectNode;
public class TestBeanConversions
extends com.fasterxml.jackson.databind.BaseMapTest
{
- final ObjectMapper mapper = new ObjectMapper();
+ final ObjectMapper MAPPER = new ObjectMapper();
static class Point {
public int x, y;
@@ -61,7 +63,7 @@
{
// should have no problems convert between compatible beans...
PointStrings input = new PointStrings("37", "-9");
- Point point = mapper.convertValue(input, Point.class);
+ Point point = MAPPER.convertValue(input, Point.class);
assertEquals(37, point.x);
assertEquals(-9, point.y);
// z not included in input, will be whatever default constructor provides
@@ -75,14 +77,14 @@
//String json = "{\"boolProp\":\"oops\"}";
// First: unknown property
try {
- mapper.readValue("{\"unknownProp\":true}", BooleanBean.class);
+ MAPPER.readValue("{\"unknownProp\":true}", BooleanBean.class);
} catch (JsonProcessingException e) {
verifyException(e, "unknownProp");
}
// then bad conversion
try {
- mapper.readValue("{\"boolProp\":\"foobar\"}", BooleanBean.class);
+ MAPPER.readValue("{\"boolProp\":\"foobar\"}", BooleanBean.class);
} catch (JsonProcessingException e) {
verifyException(e, "boolProp");
}
@@ -92,8 +94,8 @@
{
ObjectWrapper a = new ObjectWrapper("foo");
ObjectWrapper b = new ObjectWrapper(a);
- ObjectWrapper b2 = mapper.convertValue(b, ObjectWrapper.class);
- ObjectWrapper a2 = mapper.convertValue(b2.getData(), ObjectWrapper.class);
+ ObjectWrapper b2 = MAPPER.convertValue(b, ObjectWrapper.class);
+ ObjectWrapper a2 = MAPPER.convertValue(b2.getData(), ObjectWrapper.class);
assertEquals("foo", a2.getData());
}
@@ -120,6 +122,26 @@
_convertAndVerifyPoint(wrappingMapper);
}
+ // [Issue-11]: simple cast, for POJOs etc
+ public void testConvertUsingCast() throws Exception
+ {
+ String str = new String("foo");
+ CharSequence seq = str;
+ String result = MAPPER.convertValue(seq, String.class);
+ // should just cast...
+ assertSame(str, result);
+ }
+
+ // [Issue-11]: simple cast, for Tree
+ public void testNodeConvert() throws Exception
+ {
+ ObjectNode src = (ObjectNode) MAPPER.readTree("{}");
+ TreeNode node = src;
+ ObjectNode result = MAPPER.treeToValue(node, ObjectNode.class);
+ // should just cast...
+ assertSame(src, result);
+ }
+
private void _convertAndVerifyPoint(ObjectMapper m)
{
final Point input = new Point(1, 2, 3);
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/TestStringConversions.java b/src/test/java/com/fasterxml/jackson/databind/convert/TestStringConversions.java
index 6ee938a..c76e83c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/convert/TestStringConversions.java
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/TestStringConversions.java
@@ -9,13 +9,13 @@
public class TestStringConversions
extends com.fasterxml.jackson.databind.BaseMapTest
{
- final ObjectMapper mapper = new ObjectMapper();
+ final ObjectMapper MAPPER = new ObjectMapper();
public void testSimple()
{
- assertEquals(Boolean.TRUE, mapper.convertValue("true", Boolean.class));
- assertEquals(Integer.valueOf(-3), mapper.convertValue(" -3 ", Integer.class));
- assertEquals(Long.valueOf(77), mapper.convertValue("77", Long.class));
+ assertEquals(Boolean.TRUE, MAPPER.convertValue("true", Boolean.class));
+ assertEquals(Integer.valueOf(-3), MAPPER.convertValue(" -3 ", Integer.class));
+ assertEquals(Long.valueOf(77), MAPPER.convertValue("77", Long.class));
int[] ints = { 1, 2, 3 };
List<Integer> Ints = new ArrayList<Integer>();
@@ -23,38 +23,32 @@
Ints.add(2);
Ints.add(3);
- assertArrayEquals(ints, mapper.convertValue(Ints, int[].class));
+ assertArrayEquals(ints, MAPPER.convertValue(Ints, int[].class));
}
public void testStringsToInts()
{
// let's verify our "neat trick" actually works...
assertArrayEquals(new int[] { 1, 2, 3, 4, -1, 0 },
- mapper.convertValue("1 2 3 4 -1 0".split("\\s+"), int[].class));
+ MAPPER.convertValue("1 2 3 4 -1 0".split("\\s+"), int[].class));
}
- /**
- * @since 1.6
- */
public void testBytesToBase64AndBack() throws Exception
{
byte[] input = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
- String encoded = mapper.convertValue(input, String.class);
+ String encoded = MAPPER.convertValue(input, String.class);
assertNotNull(encoded);
- byte[] result = mapper.convertValue(encoded, byte[].class);
+ byte[] result = MAPPER.convertValue(encoded, byte[].class);
assertArrayEquals(input, result);
}
- /**
- * @since 1.7.3
- */
public void testBytestoCharArray() throws Exception
{
byte[] input = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
// first, do baseline encoding
- char[] expEncoded = mapper.convertValue(input, String.class).toCharArray();
+ char[] expEncoded = MAPPER.convertValue(input, String.class).toCharArray();
// then compare
- char[] actEncoded = mapper.convertValue(input, char[].class);
+ char[] actEncoded = MAPPER.convertValue(input, char[].class);
assertArrayEquals(expEncoded, actEncoded);
}
}