5

I am using Gson and I have an object that one of its fields is a Class

class A {
…
private Class aClass;
… }

When I parse the instance to Json using default Gson object aClass comes empty.

Any idea why?

Programmer Bruce
  • 64,977
  • 7
  • 99
  • 97
OZG
  • 509
  • 7
  • 19

2 Answers2

8

You need custom type adapter. Here is example:

package com.sopovs.moradanen;

import java.lang.reflect.Type;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

public class GsonClassTest {
public static void main(String[] args) {
    Gson gson = new GsonBuilder()
            .registerTypeAdapter(Class.class, new ClassTypeAdapter())
            .setPrettyPrinting()
            .create();

    String json = gson.toJson(new Foo());
    System.out.println(json);

    Foo fromJson = gson.fromJson(json, Foo.class);
    System.out.println(fromJson.boo.getName());
}

public static class ClassTypeAdapter implements JsonSerializer<Class<?>>, JsonDeserializer<Class<?>> {

    @Override
    public JsonElement serialize(Class<?> src, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(src.getName());
    }

    @Override
    public Class<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
        try {
            return Class.forName(json.getAsString());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

}

public static class Foo {
    Class<?> boo = String.class;
}
}

The output of this code is:

{
  "boo": "java.lang.String"
}
java.lang.String
Ivan Sopov
  • 2,300
  • 4
  • 21
  • 39
  • You could throw a JsonParseException instead of RuntimeException. – msteiger Mar 06 '15 at 11:27
  • 1
    **Warning:** Assuming the JSON data comes from untrusted users, this allows them to load arbitrary classes from the classpath and who knows what your application then does with these classes. In the worst case this can lead to a remote code execution vulnerability. Ideally restrict the class to some known safe subclass: `Class.forName(json.getAsString(), false, getClass().getClassLoader()).asSubclass(MyKnownBaseclass.class)` – Marcono1234 Mar 23 '23 at 20:18
3

When I parse the instance to Json using default Gson object aClass comes empty.

Any idea why?

In a comment in issue 340, a Gson project manager explains:

Serializing types is actually somewhat of a security problem, so we don't want to support it by default. A malicious .json file could cause your application to load classes that it wouldn't otherwise; depending on your class path loading certain classes could DoS your application.

But it's quite straightforward to write a type adapter to support this in your own app.

Of course, since serialization is not the same as deserialization, I don't understand how this is an explanation for the disabled serialization, unless the unmentioned notion is to in a sense "balance" the default behaviors of serialization with deserialization.

Programmer Bruce
  • 64,977
  • 7
  • 99
  • 97