#java #gson
#java #gson
Вопрос:
Я использую Gson, и у меня есть объект, одно из полей которого является классом
class A {
…
private Class aClass;
… }
Когда я анализирую экземпляр в Json, используя Gson object AClass по умолчанию, класс становится пустым.
Есть идеи, почему?
Комментарии:
1. Есть ли у вас общедоступный способ получения / установки для класса?
2. Вы преобразуете Json в объект (JSON-> Object) или преобразуете объект в строку Json (Object-> JSON)? Если вы анализируете Json, как выглядит ваше
aClass
поле?3. GSON не использует методы получения / установки. Он использует только поля в классе.
Ответ №1:
Вам нужен пользовательский адаптер типа. Вот пример:
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;
}
}
Результатом этого кода является:
{
"boo": "java.lang.String"
}
java.lang.String
Комментарии:
1. Вы могли бы вызвать исключение JsonParseException вместо исключения RuntimeException.
2. Предупреждение: Предполагая, что данные JSON поступают от ненадежных пользователей, это позволяет им загружать произвольные классы из classpath, и кто знает, что ваше приложение затем делает с этими классами. В худшем случае это может привести к уязвимости удаленного выполнения кода. В идеале ограничить класс каким-либо известным безопасным подклассом:
Class.forName(json.getAsString(), false, getClass().getClassLoader()).asSubclass(MyKnownBaseclass.class)
Ответ №2:
Когда я анализирую экземпляр в Json, используя Gson object AClass по умолчанию, класс становится пустым.
Есть идеи, почему?
В комментарии к выпуску 340 менеджер проекта Gson объясняет:
Сериализация типов на самом деле является некоторой проблемой безопасности, поэтому мы не хотим поддерживать ее по умолчанию. Вредоносный .файл json может привести к тому, что ваше приложение загрузит классы, которых оно не загрузило бы в противном случае; в зависимости от вашего пути к классу загрузка определенных классов может привести к сбою вашего приложения.
Но довольно просто написать адаптер типа для поддержки этого в вашем собственном приложении.
Конечно, поскольку сериализация — это не то же самое, что десериализация, я не понимаю, как это объясняет отключенную сериализацию, если только не упомянутое понятие не заключается в том, чтобы в некотором смысле «сбалансировать» поведение сериализации по умолчанию с десериализацией.