This is a well-known problem with Java type erasure: T is just a type variable, and you must indicate actual class, usually as Class argument. Without such information, best that can be done is to use bounds; and plain T is roughly same as 'T extends Object'. And Jackson will then bind JSON Objects as Maps.

In this case, tester method needs to have access to Class, and you can construct

JavaType type = mapper.getTypeFactory().
  constructCollectionType(List.class, Foo.class)

and then

List<Foo> list = mapper.readValue(new File("input.json"), type);
Answer from StaxMan on Stack Overflow
🌐
Fasterxml
fasterxml.github.io › jackson-core › javadoc › 2.2.0 › com › fasterxml › jackson › core › type › TypeReference.html
TypeReference (Jackson-core 2.2.0 API)
Usage is by sub-classing: here is one way to instantiate reference to generic type List<Integer>: TypeReference ref = new TypeReference<List<Integer>>() { }; which can be passed to methods that accept TypeReference, or resolved using TypeFactory to obtain ResolvedType.
🌐
DEV Community
dev.to › emilossola › a-comprehensive-guide-for-java-typereference-249m
A Comprehensive Guide for Java TypeReference - DEV Community
July 10, 2023 - In Java, TypeReference is not a built-in class. However, it is often used in libraries and frameworks to overcome the limitations of Java's type erasure during generic type resolution. Type erasure is a feature of the Java programming language that erases generic type information at runtime. This means that when you use generics, the actual type information is not available at runtime. For example, if you have a List, the type information "String" is not available at runtime due to type erasure.
🌐
GitHub
github.com › FasterXML › jackson-1 › blob › master › src › java › org › codehaus › jackson › type › TypeReference.java
jackson-1/src/java/org/codehaus/jackson/type/TypeReference.java at master · FasterXML/jackson-1
* to generic type <code>List&lt;Integer></code>: *<pre> * TypeReference ref = new TypeReference&lt;List&lt;Integer>>() { }; *</pre> * which can be passed to methods that accept TypeReference. */ public abstract class TypeReference<T> implements Comparable<TypeReference<T>> { final Type _type; ·
Author: FasterXML
Top answer
1 of 3
267

This is a well-known problem with Java type erasure: T is just a type variable, and you must indicate actual class, usually as Class argument. Without such information, best that can be done is to use bounds; and plain T is roughly same as 'T extends Object'. And Jackson will then bind JSON Objects as Maps.

In this case, tester method needs to have access to Class, and you can construct

JavaType type = mapper.getTypeFactory().
  constructCollectionType(List.class, Foo.class)

and then

List<Foo> list = mapper.readValue(new File("input.json"), type);
2 of 3
12

'JavaType' works !! I was trying to unmarshall (deserialize) a List in json String to ArrayList java Objects and was struggling to find a solution since days.
Below is the code that finally gave me solution. Code:

JsonMarshallerUnmarshaller<T> {
    T targetClass;

    public ArrayList<T> unmarshal(String jsonString) {
        ObjectMapper mapper = new ObjectMapper();

        AnnotationIntrospector introspector = new JacksonAnnotationIntrospector();
        mapper.getDeserializationConfig()
            .withAnnotationIntrospector(introspector);

        mapper.getSerializationConfig()
            .withAnnotationIntrospector(introspector);
        JavaType type = mapper.getTypeFactory().
            constructCollectionType(
                ArrayList.class, 
                targetclass.getClass());

        try {
            Class c1 = this.targetclass.getClass();
            Class c2 = this.targetclass1.getClass();
            ArrayList<T> temp = (ArrayList<T>) 
                mapper.readValue(jsonString,  type);
            return temp ;
        } catch (JsonParseException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null ;
    }  
}
🌐
Adobe Developer
developer.adobe.com › experience-manager › reference-materials › 6-5 › javadoc › com › fasterxml › jackson › core › type › TypeReference.html
TypeReference (The Adobe AEM Quickstart and Web Application.)
Usage is by sub-classing: here is one way to instantiate reference to generic type List<Integer>: TypeReference ref = new TypeReference<List<Integer>>() { }; which can be passed to methods that accept TypeReference, or resolved using TypeFactory to obtain ResolvedType.
🌐
Northcoder
northcoder.com › post › jackson-object-mapper-which-way-is
Jackson's ObjectMapper and TypeReference | northCoder
January 15, 2021 - TypeReference is an abstract class. The {} provides an empty implementation via an anonymous class, without which you would get a compile-time error: ... You may sometimes (rarely?) see {{}} syntax - this is Java’s double brace initialization. Consider this code: ... This creates a list containing two values.
🌐
Medium
medium.com › @poojaauma › enhancing-deserialization-safety-in-java-with-typereference-ea110ece6994
Enhancing Deserialization Safety in Java with TypeReference | by Umadevi R | Medium
November 7, 2024 - When working with JSON in Java, you’ve probably come across situations where deserializing JSON into complex or generic types like List<User> or Map<String, Object> can be challenging. Java’s type erasure makes it hard for libraries like Jackson to determine the exact type of collection elements, which can lead to runtime errors or even vulnerabilities. Fortunately, Jackson’s TypeReference offers a solution to these problems.
🌐
Stack Overflow
stackoverflow.com › questions › 51618901 › typereference-with-generic-parameter-to-deserialize-list-of-objects
java - TypeReference with generic parameter to deserialize list of objects - Stack Overflow
public List<Cat> getCats() { String url = this.BASE_URL + "/cats"; return getDataFromAPI(url, new TypeReference<List<Cat>>() {}); } public List<Dog> getDogs() { String url = this.BASE_URL + "/dogs"; return getDataFromAPI(url, new TypeReference<List<Dog>>() {}); } public <T> T getDataFromAPI(String url, TypeReference<T> typeRef) { //restTemplate is Spring RestTemplate Map<String, List<Map<String, Object>>> response = this.restTemplate.getForObject(url, Map.class); //objectMapper is Jackson ObjectMapper return this.objectMapper.convertValue(response.get("response"), typeReference); }
Find elsewhere
🌐
Javadoc.io
javadoc.io › static › org.codehaus.jackson › jackson-core-asl › 1.9.13 › org › codehaus › jackson › type › TypeReference.html
TypeReference (Jackson JSON Processor)
Usage is by sub-classing: here is one way to instantiate reference to generic type List<Integer>: TypeReference ref = new TypeReference<List<Integer>>() { }; which can be passed to methods that accept TypeReference.
🌐
Adobe Developer
developer.adobe.com › experience-manager › reference-materials › cloud-service › javadoc › com › fasterxml › jackson › core › type › TypeReference.html
TypeReference (The Adobe Experience Manager SDK 2022.11.9850.20221116T162329Z-220900)
Usage is by sub-classing: here is one way to instantiate reference to generic type List<Integer>: TypeReference ref = new TypeReference<List<Integer>>() { }; which can be passed to methods that accept TypeReference, or resolved using TypeFactory to obtain ResolvedType.
🌐
Java Tips
javatips.net › api › com.fasterxml.jackson.core.type.typereference
Java Examples for com.fasterxml.jackson.core.type.TypeReference
@Override public Map<String, Object> getJsonMap(String json) { HashMap<String, Object> result = null; TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() { }; try { result = JSON.getDefaultObjectMapper().readValue(json, typeRef); } catch (Exception e) { e.printStackTrace(); } return result; } ... public static List<RoleRepresentation> fromJson(String roleJson) { List<RoleRepresentation> roles = null; try { ObjectMapper mapper = new ObjectMapper(); roles = mapper.readValue(roleJson, new TypeReference<List<RoleRepresentation>>() { }); } catch (JsonMappin
🌐
Spring
docs.spring.io › spring-framework › docs › current › javadoc-api › org › springframework › asm › TypeReference.html
TypeReference (Spring Framework 7.0.8 API)
java.lang.Object · org.springframework.asm.TypeReference · public class TypeReference extends Object · A reference to a type appearing in a class, field or method declaration, or on an instruction.
Top answer
1 of 2
26

In Java generics are more or less gone at runtime. This is called type erasure. So your HashMap<String, Object> will just be HashMap<?, ?> when your programme runs. So Jackson cannot determine the types Stringand Object. That is why you have to create a TypeReference which will preserve that information at runtime so Jackson can deserialise your JSON String into the correct classes.

If you don't specify a type Jackson will still be able to correctly deserialise simple objects like String or numbers but when a more complex object is encountered it will simply deserialise them into LinkedHashMap which will then most likely lead to a ClassCastException when you try to access the deserialised object.

2 of 2
9

This TypeReference<T> implements Comparable<TypeReference<T>> is part of jackon library. And this is part of com.fasterxml.jackson.core.type. From the API documentation:

This generic abstract class is used for obtaining full generics type information by sub-classing; it must be converted to ResolvedType implementation (implemented by JavaType from "databind" bundle) to be used. Class is based on ideas from http://gafter.blogspot.com/2006/12/super-type-tokens.html, Additional idea (from a suggestion made in comments of the article) is to require bogus implementation of Comparable (any such generic interface would do, as long as it forces a method with generic type to be implemented). to ensure that a Type argument is indeed given. Usage is by sub-classing: here is one way to instantiate reference to generic type List:

TypeReference ref = new TypeReference<List>() { }; which can be passed to methods that accept TypeReference, or resolved using TypeFactory to obtain ResolvedType.

This is basically used to de-serialize the Generic type of JSON objects, for example the JAVA Collection objects as below:

public List<Double> getDoubleList() {

  return getObjectFromJson(new TypeReference<List<Double>>() {
  });
}


public <T> T getObjectFromJson(String jsonString, final TypeReference<T> typeReference) {
  try {
    return new ObjectMapper().readValue(jsonString, typeReference);
  } catch (JsonProcessingException e) {
    // TODO
  }
}
🌐
Javadoc.io
javadoc.io › doc › com.fasterxml.jackson.core › jackson-core › latest › com › fasterxml › jackson › core › type › TypeReference.html
TypeReference - jackson-core 2.22.3 javadoc
Bookmarks · Latest version of com.fasterxml.jackson.core:jackson-core · https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-core · Current version 2.22.3 · https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-core/2.22.3 · package-list path (used for javadoc generation -link ...
🌐
Microsoft Learn
learn.microsoft.com › en-us › java › api › com.azure.core.util.serializer.typereference
TypeReference<T> Class - Java
This method will cache the instance of TypeReference<T> using the passed Class as the key. This is meant to be used with non-generic types such as primitive object types and POJOs, not Map or List parameterized types.
🌐
CodingTechRoom
codingtechroom.com › question › -java-jackson-typereference-explained
Understanding TypeReference in Java with Jackson - CodingTechRoom
ObjectMapper objectMapper = new ... {}); TypeReference is a utility class in Jackson that enables developers to define generic types when working with serialization and deserialization....
🌐
Fasterxml
fasterxml.github.io › jackson-core › javadoc › 2.8 › com › fasterxml › jackson › core › type › TypeReference.html
TypeReference (Jackson-core 2.8.0 API)
Usage is by sub-classing: here is one way to instantiate reference to generic type List<Integer>: TypeReference ref = new TypeReference<List<Integer>>() { }; which can be passed to methods that accept TypeReference, or resolved using TypeFactory to obtain ResolvedType.
🌐
Spring
docs.spring.io › spring-framework › docs › 5.1.8.RELEASE_to_5.1.9.RELEASE › Spring Framework 5.1.9.RELEASE › org › springframework › asm › TypeReference.html
TypeReference
The target_type and target_info structures - as defined in the Java Virtual Machine Specification (JVMS) - corresponding to this type reference. target_type uses one byte, and all the target_info union fields use up to 3 bytes (except localvar_target, handled with the specific method MethodVisitor.visitLocalVariableAnnotation(int, org.springframework.asm.TypePath, org.springframework.asm.Label[], org.springframework.asm.Label[], int[], java.lang.String, boolean)). Thus, both structures can be stored in an int. This int field stores target_type (called the TypeReference 'sort' in the public API of this class) in its most significant byte, followed by the target_info fields.