Added more unit tests for type handling; found problems with handling of EnumSet, fixed some, one remains (generic problem with type narrowing, affects other types too);5
diff --git a/src/mapper/java/org/codehaus/jackson/map/DeserializerFactory.java b/src/mapper/java/org/codehaus/jackson/map/DeserializerFactory.java
index c323d01..6b650bc 100644
--- a/src/mapper/java/org/codehaus/jackson/map/DeserializerFactory.java
+++ b/src/mapper/java/org/codehaus/jackson/map/DeserializerFactory.java
@@ -12,13 +12,13 @@
* Since there are multiple broad categories of deserializers, there are
* multiple factory methods:
*<ul>
- * <li>There is one method to support Json scalar types: here access is
+ * <li>There is one method to support JSON scalar types: here access is
* by declared value type
* </li>
- * <li>For Json "Array" type, we need 2 methods: one to deal with expected
+ * <li>For JSON "Array" type, we need 2 methods: one to deal with expected
* Java arrays; and the other for other Java containers (Lists, Sets)
* </li>
- * <li>For Json "Object" type, we need 2 methods: one to deal with
+ * <li>For JSON "Object" type, we need 2 methods: one to deal with
* expected Java {@link java.util.Map}s, and another for actual
* Java objects (beans)
* </li>
diff --git a/src/mapper/java/org/codehaus/jackson/map/deser/BasicDeserializerFactory.java b/src/mapper/java/org/codehaus/jackson/map/deser/BasicDeserializerFactory.java
index 7d0a235..9bde319 100644
--- a/src/mapper/java/org/codehaus/jackson/map/deser/BasicDeserializerFactory.java
+++ b/src/mapper/java/org/codehaus/jackson/map/deser/BasicDeserializerFactory.java
@@ -145,7 +145,6 @@
throws JsonMappingException
{
Class<?> collectionClass = type.getRawClass();
-
BasicBeanDescription beanDesc = config.introspectClassAnnotations(collectionClass);
// Explicit deserializer to use? (@JsonDeserialize.using)
JsonDeserializer<Object> deser = findDeserializerFromAnnotation(config, beanDesc.getClassInfo());
diff --git a/src/mapper/java/org/codehaus/jackson/map/deser/EnumSetDeserializer.java b/src/mapper/java/org/codehaus/jackson/map/deser/EnumSetDeserializer.java
index 09469b0..9ead04d 100644
--- a/src/mapper/java/org/codehaus/jackson/map/deser/EnumSetDeserializer.java
+++ b/src/mapper/java/org/codehaus/jackson/map/deser/EnumSetDeserializer.java
@@ -65,7 +65,6 @@
TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
- // should never actually get called (enums are not polymorphic), but...
return typeDeserializer.deserializeTypedFromArray(jp, ctxt);
}
diff --git a/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeSerializerBase.java b/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeSerializerBase.java
index 6d83390..2983214 100644
--- a/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeSerializerBase.java
+++ b/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeSerializerBase.java
@@ -1,5 +1,7 @@
package org.codehaus.jackson.map.jsontype.impl;
+import java.util.*;
+
import org.codehaus.jackson.map.TypeSerializer;
import org.codehaus.jackson.map.annotate.JsonTypeInfo;
import org.codehaus.jackson.type.JavaType;
@@ -48,10 +50,21 @@
public final static class ClassNameConverter extends TypeConverter
{
public final static ClassNameConverter instance = new ClassNameConverter();
-
+
public JsonTypeInfo.Id idType() { return JsonTypeInfo.Id.CLASS; }
- public String typeAsString(Object value) {
- return value.getClass().getName();
+ public String typeAsString(Object value)
+ {
+ String str = value.getClass().getName();
+ /* 25-Jan-2009, tatus: There are some internal classes that
+ * we can not access as is. We need better mechanism; for
+ * now this has to do...
+ */
+ if (str.startsWith("java.")) {
+ if (value instanceof EnumSet<?>) { // Regular- and JumboEnumSet...
+ str = EnumSet.class.getName();
+ }
+ }
+ return str;
}
}
diff --git a/src/mapper/java/org/codehaus/jackson/map/ser/EnumSerializer.java b/src/mapper/java/org/codehaus/jackson/map/ser/EnumSerializer.java
index 4c12d8a..2fcd20a 100644
--- a/src/mapper/java/org/codehaus/jackson/map/ser/EnumSerializer.java
+++ b/src/mapper/java/org/codehaus/jackson/map/ser/EnumSerializer.java
@@ -11,8 +11,16 @@
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.type.JavaType;
+/**
+ * Standard serializer used for all enum types.
+ *<p>
+ * Based on {@link ScalarSerializerBase} since the JSON value is
+ * scalar (String).
+ *
+ * @author tatu
+ */
public class EnumSerializer
- extends SerializerBase<Enum<?>>
+ extends ScalarSerializerBase<Enum<?>>
{
/**
* This map contains pre-resolved values (since there are ways
diff --git a/src/mapper/java/org/codehaus/jackson/map/ser/ScalarSerializerBase.java b/src/mapper/java/org/codehaus/jackson/map/ser/ScalarSerializerBase.java
index cd4279b..47136a2 100644
--- a/src/mapper/java/org/codehaus/jackson/map/ser/ScalarSerializerBase.java
+++ b/src/mapper/java/org/codehaus/jackson/map/ser/ScalarSerializerBase.java
@@ -15,6 +15,15 @@
}
/**
+ * Alternate constructor that is (alas!) needed to work
+ * around kinks of generic type handling
+ */
+ @SuppressWarnings("unchecked")
+ protected ScalarSerializerBase(Class<?> t, boolean dummy) {
+ super((Class<T>) t);
+ }
+
+ /**
* Default implementation will write type prefix, call regular serialization
* method (since assumption is that value itself does not need JSON
* Array or Object start/end markers), and then write type suffix.
diff --git a/src/mapper/java/org/codehaus/jackson/map/ser/SerializerBase.java b/src/mapper/java/org/codehaus/jackson/map/ser/SerializerBase.java
index 95acb48..e714809 100644
--- a/src/mapper/java/org/codehaus/jackson/map/ser/SerializerBase.java
+++ b/src/mapper/java/org/codehaus/jackson/map/ser/SerializerBase.java
@@ -31,8 +31,6 @@
/**
* Alternate constructor that is (alas!) needed to work
* around kinks of generic type handling
- *
- * @param t
*/
@SuppressWarnings("unchecked")
protected SerializerBase(Class<?> t, boolean dummy) {
diff --git a/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForObject.java b/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForObject.java
index e5da3a6..f86dfe2 100644
--- a/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForObject.java
+++ b/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForObject.java
@@ -22,6 +22,8 @@
protected StringBean(String n) { name = n; }
}
+ enum Choice { YES, NO; }
+
/*
******************************************************
* Unit tests
@@ -102,4 +104,40 @@
assertEquals("xyz", ((StringBean) beans[0]).name);
}
+ public void testEnumAsObject() throws Exception
+ {
+ // wrapping to be declared as object
+ Object[] input = new Object[] { Choice.YES };
+ // first, without type info:
+ assertEquals("[\"YES\"]", serializeAsString(input));
+
+ // and then with it
+ ObjectMapper m = new ObjectMapper();
+ m.enableDefaultTyping();
+ String json = m.writeValueAsString(input);
+ assertEquals("[[\""+Choice.class.getName()+"\",\"YES\"]]", json);
+
+ // which we should get back same way
+ Object[] output = m.readValue(json, Object[].class);
+ assertEquals(1, output.length);
+ assertEquals(Choice.YES, output[0]);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testEnumSet() throws Exception
+ {
+ EnumSet<Choice> set = EnumSet.of(Choice.NO);
+ Object[] input = new Object[] { set };
+ ObjectMapper m = new ObjectMapper();
+ m.enableDefaultTyping();
+ String json = m.writeValueAsString(input);
+ Object[] output = m.readValue(json, Object[].class);
+ assertEquals(1, output.length);
+ Object ob = output[0];
+ assertEquals(EnumSet.class, ob.getClass());
+ EnumSet<Choice> set2 = (EnumSet<Choice>) ob;
+ assertEquals(1, set2.size());
+ assertTrue(set2.contains(Choice.NO));
+ assertFalse(set2.contains(Choice.YES));
+ }
}