Merge pull request #423 from sergeymetallic/patch-1

Update CalendarSerializer.java
diff --git a/release-notes/CREDITS b/release-notes/CREDITS
index cb72ea5..4da5f72 100644
--- a/release-notes/CREDITS
+++ b/release-notes/CREDITS
@@ -111,4 +111,8 @@
   * Contributed #407: Make array and Collection serializers use configured value null handler
    (2.4.0)
 
+Cemalettin Koc: (cemo@github)
+
+  * Reported #353: Problems with polymorphic types, `JsonNode` (related to #88)
+   (2.4.0)
 
diff --git a/release-notes/VERSION b/release-notes/VERSION
index e86848c..3fc975c 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -3,6 +3,8 @@
 
 #88: Prevent use of type information for `JsonNode` via default typing
  (reported by electricmonk@github)
+#353: Problems with polymorphic types, `JsonNode` (related to #88)
+ (reported by cemo@github)
 #381: Allow inlining/unwrapping of value from single-component JSON array
  (contributed by yinzara@github)
 #407: Properly use null handlers for value types when serializer Collection
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
index 63ec3a9..2573804 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
@@ -222,7 +222,7 @@
             TimeZone.getTimeZone("GMT"),
             Base64Variants.getDefaultVariant() // 2.1
     );
-    
+
     /*
     /**********************************************************
     /* Configuration settings, shared
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializers.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializers.java
index 93a92fe..f205080 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializers.java
@@ -30,16 +30,19 @@
         if (cls == String.class) {
             return DEFAULT_STRING_SERIALIZER;
         }
-        if (cls == Object.class) {
+        if (cls == Object.class || cls.isPrimitive() || Number.class.isAssignableFrom(cls)) {
             return DEFAULT_KEY_SERIALIZER;
         }
-        // [JACKSON-606] special handling for dates...
         if (Date.class.isAssignableFrom(cls)) {
             return (JsonSerializer<Object>) DateKeySerializer.instance;
         }
         if (Calendar.class.isAssignableFrom(cls)) {
             return (JsonSerializer<Object>) CalendarKeySerializer.instance;
         }
+        /* 14-Mar-2014, tatu: Should support @JsonValue, as per #47; but that
+         *   requires extensive introspection, and passing in more information
+         *   to this method.
+         */
         // If no match, just use default one:
         return DEFAULT_KEY_SERIALIZER;
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestJsonPointer.java b/src/test/java/com/fasterxml/jackson/databind/node/TestJsonPointer.java
index bf2da1e..e99356a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestJsonPointer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestJsonPointer.java
@@ -31,4 +31,19 @@
         assertTrue(SAMPLE_ROOT.at("/Image/Depth").isMissingNode());
         assertTrue(SAMPLE_ROOT.at("/Image/1").isMissingNode());
     }
+
+    // To help verify [Core#133]; should be fine with "big numbers" as property keys
+    public void testLongNumbers() throws Exception
+    {
+        
+        // First, with small int key
+        JsonNode root = objectMapper().readTree("{\"123\" : 456}");
+        JsonNode jn2 = root.at("/123"); 
+        assertEquals(456, jn2.asInt());
+
+        // and then with above int-32:
+        root = objectMapper().readTree("{\"35361706045\" : 1234}");
+        jn2 = root.at("/35361706045"); 
+        assertEquals(1234, jn2.asInt());
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestTreeWithType.java b/src/test/java/com/fasterxml/jackson/databind/node/TestTreeWithType.java
new file mode 100644
index 0000000..d02ff8c
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestTreeWithType.java
@@ -0,0 +1,126 @@
+package com.fasterxml.jackson.databind.node;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+public class TestTreeWithType extends BaseMapTest
+{
+    public static class Foo {
+        public String bar;
+
+        public Foo() { }
+
+        public Foo(String bar) {
+            this.bar = bar;
+        }
+    }
+
+    // [Issue#353]
+    public class SavedCookie {
+        public String name, value;
+
+        public SavedCookie() { }
+        public SavedCookie(String n, String v) {
+            name = n;
+            value = v;
+        }
+    }
+
+    public class SavedCookieDeserializer extends JsonDeserializer<SavedCookie> {
+        @Override
+        public SavedCookie deserialize(JsonParser jsonParser, DeserializationContext ctxt)
+                throws IOException {
+           ObjectCodec oc = jsonParser.getCodec();
+           JsonNode node = oc.readTree(jsonParser);
+           return new SavedCookie(node.path("name").textValue(),
+                   node.path("value").textValue());
+        }
+
+        @Override
+        public SavedCookie deserializeWithType(JsonParser jp, DeserializationContext ctxt,
+                TypeDeserializer typeDeserializer)
+            throws IOException, JsonProcessingException
+        {
+            return (SavedCookie) typeDeserializer.deserializeTypedFromObject(jp, ctxt);
+        }
+    }    
+    
+    /*
+    /**********************************************************
+    /* Unit tests
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    public void testValueAsStringWithoutDefaultTyping() throws Exception {
+
+        Foo foo = new Foo("baz");
+        String json = MAPPER.writeValueAsString(foo);
+
+        JsonNode jsonNode = MAPPER.readTree(json);
+        assertEquals(jsonNode.get("bar").textValue(), foo.bar);
+    }
+
+    public void testValueAsStringWithDefaultTyping() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+
+        Foo foo = new Foo("baz");
+        String json = mapper.writeValueAsString(foo);
+
+        JsonNode jsonNode = mapper.readTree(json);
+        assertEquals(jsonNode.get("bar").textValue(), foo.bar);
+    }
+
+    public void testReadTreeWithDefaultTyping() throws Exception
+    {
+        final String CLASS = Foo.class.getName();
+
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL,
+                JsonTypeInfo.As.PROPERTY);
+        String json = "{\"@class\":\""+CLASS+"\",\"bar\":\"baz\"}";
+        JsonNode jsonNode = mapper.readTree(json);
+        assertEquals(jsonNode.get("bar").textValue(), "baz");
+    }
+
+    public void testValueToTreeWithoutDefaultTyping() throws Exception {
+
+        Foo foo = new Foo("baz");
+        JsonNode jsonNode = MAPPER.valueToTree(foo);
+        assertEquals(jsonNode.get("bar").textValue(), foo.bar);
+    }
+
+    public void testValueToTreeWithDefaultTyping() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+
+        Foo foo = new Foo("baz");
+        JsonNode jsonNode = mapper.valueToTree(foo);
+        assertEquals(jsonNode.get("bar").textValue(), foo.bar);
+    }
+
+    public void testIssue353() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+
+        mapper.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL, "@class");
+
+         SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null, "TEST", "TEST"));
+         testModule.addDeserializer(SavedCookie.class, new SavedCookieDeserializer());
+         mapper.registerModule(testModule);
+
+         SavedCookie savedCookie = new SavedCookie("key", "v");
+         String json = mapper.writeValueAsString(savedCookie);
+         SavedCookie out = mapper.reader(SavedCookie.class).readValue(json);
+
+         assertEquals("key", out.name);
+         assertEquals("v", out.value);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestMapJsonValueKey.java b/src/test/java/com/fasterxml/jackson/failing/TestMapJsonValueKey.java
index 0be19b3..2b76dd9 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestMapJsonValueKey.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestMapJsonValueKey.java
@@ -5,45 +5,40 @@
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonValue;
-import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.test.BaseTest;
 
-public class TestMapJsonValueKey extends BaseTest
+// [Issue#47]
+public class TestMapJsonValueKey extends BaseMapTest
 {
     public static class Wat
     {
         private final String wat;
 
         @JsonCreator
-        Wat(String wat)
-        {
+        Wat(String wat) {
             this.wat = wat;
         }
 
         @JsonValue
-        public String getWat()
-        {
+        public String getWat() {
             return wat;
         }
 
         @Override
-        public String toString()
-        {
-            return "[Wat: " + wat + "]";
+        public String toString() {
+            return "(String)[Wat: " + wat + "]";
         }
     }
 
     public void testMapJsonValueKey()
     throws Exception
     {
-        Map<Wat, Boolean> map = new HashMap<Wat, Boolean>();
-        map.put(new Wat("3"), true);
-        map.put(new Wat("x"), false);
-
-        TypeReference<Map<Wat, Boolean>> type = new TypeReference<Map<Wat, Boolean>>(){};
+        Map<Wat, Boolean> input = new HashMap<Wat, Boolean>();
+        input.put(new Wat("3"), true);
 
         ObjectMapper mapper = new ObjectMapper();
-        assertEquals(map, mapper.readValue(mapper.writeValueAsBytes(map), type));
+        String json = mapper.writeValueAsString(input);
+        assertEquals(aposToQuotes("{'3':'true'}"), json);
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestTreeWithType.java b/src/test/java/com/fasterxml/jackson/failing/TestTreeWithType.java
deleted file mode 100644
index 5842792..0000000
--- a/src/test/java/com/fasterxml/jackson/failing/TestTreeWithType.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.fasterxml.jackson.failing;
-
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.databind.*;
-
-public class TestTreeWithType extends BaseMapTest
-{
-    public static class Foo {
-        public String bar;
-
-        public Foo() { }
-
-        public Foo(String bar) {
-            this.bar = bar;
-        }
-    }
-    
-    /*
-    /**********************************************************
-    /* Unit tests
-    /**********************************************************
-     */
-
-    private final ObjectMapper mapper = new ObjectMapper();
-
-    public void testValueAsStringWithoutDefaultTyping() throws Exception {
-
-        Foo foo = new Foo("baz");
-        String json = mapper.writeValueAsString(foo);
-
-        JsonNode jsonNode = mapper.readTree(json);
-        assertEquals(jsonNode.get("bar").textValue(), foo.bar);
-    }
-
-    public void testValueAsStringWithDefaultTyping() throws Exception {
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
-
-        Foo foo = new Foo("baz");
-        String json = mapper.writeValueAsString(foo);
-
-        JsonNode jsonNode = mapper.readTree(json);
-        assertEquals(jsonNode.get("bar").textValue(), foo.bar);
-    }
-
-    public void testReadTreeWithDefaultTyping() throws Exception
-    {
-        final String CLASS = Foo.class.getName();
-
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL,
-                JsonTypeInfo.As.PROPERTY);
-        String json = "{\"@class\":\""+CLASS+"\",\"bar\":\"baz\"}";
-        JsonNode jsonNode = mapper.readTree(json);
-        assertEquals(jsonNode.get("bar").textValue(), "baz");
-    }
-
-    public void testValueToTreeWithoutDefaultTyping() throws Exception {
-
-        Foo foo = new Foo("baz");
-        JsonNode jsonNode = mapper.valueToTree(foo);
-        assertEquals(jsonNode.get("bar").textValue(), foo.bar);
-    }
-
-    public void testValueToTreeWithDefaultTyping() throws Exception {
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
-
-        Foo foo = new Foo("baz");
-        JsonNode jsonNode = mapper.valueToTree(foo);
-        assertEquals(jsonNode.get("bar").textValue(), foo.bar);
-    }
-}