diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java index 140872e85f..16a6dec995 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java +++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java @@ -3055,6 +3055,23 @@ public T readValue(JsonParser p, Class valueType) return (T) _readValue(getDeserializationConfig(), p, _typeFactory.constructType(valueType)); } + /** + * Reads the value from the given JSON content and automatically detects the class type. + * + * @param the type of the object to read + * @param p the JsonParser + * @param reified don't pass any values here. It's a trick to detect the class type. + * @return the deserialized object + * @throws JsonProcessingException if there is a problem processing the JSON + */ + public T readValue(JsonParser p, T... reified) throws IOException { + if (reified.length > 0) { + throw new IllegalArgumentException("Please don't pass any values here. Java will detect class automatically."); + } + + return readValue(p, _typeFactory.constructType(getClassOf(reified))); + } + /** * Method to deserialize JSON content into a Java type, reference * to which is passed as argument. Type is passed using so-called @@ -3855,6 +3872,34 @@ public T readValue(String content, Class valueType) return readValue(content, _typeFactory.constructType(valueType)); } + /** + * 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 + */ + private static Class getClassOf(T[] array) { + return (Class) array.getClass().getComponentType(); + } + + /** + * Reads the value from the given JSON content and automatically detects the class type. + * + * @param the type of the object to read + * @param content the JSON string + * @param reified don't pass any values here. It's a trick to detect the class type. + * @return the deserialized object + * @throws JsonProcessingException if there is a problem processing the JSON + */ + public T readValue(String content, T... reified) throws JsonProcessingException { + if (reified.length > 0) { + throw new IllegalArgumentException("Please don't pass any values here. Java will detect class automatically."); + } + + return readValue(content, _typeFactory.constructType(getClassOf(reified))); + } + /** * Method to deserialize JSON content from given JSON content String. * @@ -3957,6 +4002,15 @@ public T readValue(byte[] src, int offset, int len, return (T) _readMapAndClose(_jsonFactory.createParser(src, offset, len), _typeFactory.constructType(valueType)); } + @SuppressWarnings("unchecked") + public T readValue(byte[] src, int offset, int len, T... reified) throws IOException { + if (reified.length > 0) { + throw new IllegalArgumentException("Please don't pass any values here. Java will detect class automatically."); + } + + return readValue(src, offset, len, _typeFactory.constructType(getClassOf(reified))); + } + @SuppressWarnings({ "unchecked" }) public T readValue(byte[] src, TypeReference valueTypeRef) throws IOException, StreamReadException, DatabindException diff --git a/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java b/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java index a249682b76..ef5198e84a 100644 --- a/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java @@ -385,6 +385,16 @@ public void testJsonFactoryLinkage() assertSame(m, f.getCodec()); } + @Test + public void testAutoDetectClasses() throws Exception + { + ObjectMapper m = new ObjectMapper(); + final String JSON = "{ \"x\" : 3 }"; + + Bean bean = m.readValue(JSON); + assertNotNull(bean); + } + @Test public void testProviderConfig() throws Exception { diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/JacksonTypesDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/JacksonTypesDeserTest.java index 922cd34a04..a55440f1d9 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/JacksonTypesDeserTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/JacksonTypesDeserTest.java @@ -82,6 +82,50 @@ public void testTokenBufferWithSample() throws Exception } } + @Test + public void testTokenBufferWithSequenceWithAutoDetectClass() throws Exception + { + final ObjectMapper mapper = jsonMapperBuilder() + .disable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS) + .build(); + + // and then sequence of other things + JsonParser p = mapper.createParser("[ 32, [ 1 ], \"abc\", { \"a\" : true } ]"); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + TokenBuffer buf = mapper.readValue(p); + + // check manually... + JsonParser bufParser = buf.asParser(); + assertToken(JsonToken.VALUE_NUMBER_INT, bufParser.nextToken()); + assertEquals(32, bufParser.getIntValue()); + assertNull(bufParser.nextToken()); + + // then bind to another + buf = mapper.readValue(p); + bufParser = buf.asParser(); + assertToken(JsonToken.START_ARRAY, bufParser.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, bufParser.nextToken()); + assertEquals(1, bufParser.getIntValue()); + assertToken(JsonToken.END_ARRAY, bufParser.nextToken()); + assertNull(bufParser.nextToken()); + + // third one, with automatic binding + buf = mapper.readValue(p); + String str = mapper.readValue(buf.asParser()); + assertEquals("abc", str); + + // and ditto for last one + buf = mapper.readValue(p, TokenBuffer.class); + Map map = mapper.readValue(buf.asParser()); + assertEquals(1, map.size()); + assertEquals(Boolean.TRUE, map.get("a")); + + assertEquals(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + } + @SuppressWarnings("resource") @Test public void testTokenBufferWithSequence() throws Exception