diff --git a/src/main/java/tools/jackson/databind/ObjectMapper.java b/src/main/java/tools/jackson/databind/ObjectMapper.java index 97732c13a0..c1cfb4e47f 100644 --- a/src/main/java/tools/jackson/databind/ObjectMapper.java +++ b/src/main/java/tools/jackson/databind/ObjectMapper.java @@ -7,6 +7,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; @@ -2230,6 +2231,45 @@ public ObjectReader readerForMapOf(Class type) { null, _injectableValues); } + /** + * Factory method for constructing {@link ObjectReader} that will + * read or update instances of auto-detected type; inferred from compiled + * info. Note that the nominal parameter MUST be an empty array; + * otherwise an exception will be thrown. + * Usage: + *
+     *  MyType result = objectMapper.readerForDetectedType().readValue(json);
+     *
+ * + * @since 3.0 + */ + public ObjectReader readerForDetectedType(T... reified) { + // Should be auto-generated empty array; verify + Objects.requireNonNull(reified, "reified"); + if (reified.length != 0) { + throw new IllegalArgumentException(String.format( +"argument \reified\" should be empty; has %d elements", reified.length)); + } + Type type = _getClassOf(reified); +System.err.println("DEBUG: reified type: "+type); + _assertNotNull("type", type); + return _newReader(deserializationConfig(), _typeFactory.constructType(type), null, + null, _injectableValues); + } + + /** + * Utility method to get the class type from a varargs array. + * + * @param the generic type + * @param array the varargs array + * @return the class of the array component + * + * @since 3.0 + */ + private static Class _getClassOf(T[] array) { + return (Class) array.getClass().getComponentType(); + } + /** * Factory method for constructing {@link ObjectReader} that will * use specified {@link JsonNodeFactory} for constructing JSON trees. diff --git a/src/test/java/tools/jackson/databind/ObjectReaderTest.java b/src/test/java/tools/jackson/databind/ObjectReaderTest.java index 759f2f1890..a5ad12ebb1 100644 --- a/src/test/java/tools/jackson/databind/ObjectReaderTest.java +++ b/src/test/java/tools/jackson/databind/ObjectReaderTest.java @@ -90,7 +90,7 @@ public void testReaderForArrayOf() throws Exception assertEquals(ABC.C, abcs[1]); } - // [databind#2693]: convenience read methods: + // [databind#2693]: convenience read methods @Test public void testReaderForListOf() throws Exception { @@ -100,7 +100,7 @@ public void testReaderForListOf() throws Exception assertEquals(Arrays.asList(ABC.B, ABC.C), value); } - // [databind#2693]: convenience read methods: + // [databind#2693]: convenience read methods @Test public void testReaderForMapOf() throws Exception { @@ -110,6 +110,29 @@ public void testReaderForMapOf() throws Exception assertEquals(Collections.singletonMap("key", ABC.B), value); } + // [databind#5064]: auto-detection of type + @Test + public void testReaderForDetectedType() throws Exception + { + // First, regular "untyped" (java.lang.Object) + List ob = MAPPER.readerForDetectedType() + .readValue("[1]"); + assertNotNull(ob); + assertEquals(1, ob.get(0)); + + // then simple pojo + Point point = MAPPER.readerForDetectedType().readValue("{\"x\":1,\"y\":2}"); + assertNotNull(point); + assertEquals(1, point.x); + assertEquals(2, point.y); + + // and more complex + POJO pojo = MAPPER.readerForDetectedType().readValue("{\"name\":{\"value\":123}}"); + assertNotNull(pojo); + assertNotNull(pojo.name); + assertEquals(Map.of("value", 123), pojo.name); + } + /* /********************************************************** /* Test methods, some alternative JSON settings