Backend Development 9 min read

Understanding Generic Type Erasure and Fastjson Deserialization with TypeReference in Java

This article explains how Java's generic type erasure affects Fastjson deserialization, demonstrates common mistakes, and shows the correct way to deserialize generic fields using Fastjson's TypeReference, while also revealing the inner workings of TypeReference through reflection and anonymous classes.

IT Services Circle
IT Services Circle
IT Services Circle
Understanding Generic Type Erasure and Fastjson Deserialization with TypeReference in Java

In a previous article we discussed Java generic type erasure; this post addresses how to deserialize a generic entity using Fastjson and why the process can be confusing.

We define a generic class @Data public class Foo { private String val; private T obj; } and observe that after compilation the generic type T is erased to Object . When Fastjson parses JSON without specifying the generic type, the obj field is deserialized as a JSONObject instead of the expected User object.

Two incorrect attempts are shown:

Directly specifying Foo foo = JSONObject.parseObject(jsonStr, Foo.class); leads to a ClassCastException because Fastjson cannot infer the generic type.

Using a forced cast Foo foo = (Foo ) JSONObject.parseObject(jsonStr, Foo.class); compiles but still yields a JSONObject for obj .

The proper solution is to use Fastjson's TypeReference :

public class TypeRefTest {
    public static void main(String[] args) {
        String jsonStr = "{\"obj\":{\"name\":\"Hydra\",\"age\":\"18\"},\"val\":\"str\"}";
        Foo
foo2 = JSONObject.parseObject(jsonStr, new TypeReference
>(){});
        System.out.println(foo2);
        System.out.println(foo2.getObj().getClass());
    }
}

Running this prints Foo(val=str, obj=User(name=Hydra, age=18)) and confirms that obj is of type User .

The article then dives into how TypeReference works: an anonymous subclass is created, its constructor captures the generic superclass via getClass().getGenericSuperclass() , extracts the actual type argument with ((ParameterizedType) superClass).getActualTypeArguments()[0] , and caches it. This constructor is invoked twice—once for the static LIST_STRING field and once for the anonymous subclass used in deserialization.

To illustrate generic type retrieval, the author shows that creating an anonymous subclass of a generic class (e.g., new HashMap (){} ) allows access to the generic parameters via reflection, whereas a plain instance does not.

Finally, the article wraps up the exploration and invites readers to experiment further with the source code.

JavareflectiongenericsfastjsondeserializationTypeReference
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.