Gson десериализуется в универсальный тип Map - PullRequest
1 голос
/ 21 сентября 2011

Попытка десериализации JSON на картугде K - String, а V - один из нескольких типов (т. е. String int или boolean).Используя Gson, я попробовал следующий код:

public static void main(String[] args) {
JsonObject json = new JsonObject(); 
json.addProperty("str", "str-value");
json.addProperty("int", 10);
json.addProperty("bool", true);
// "json" now contains {"str":"str-value","int":10,"bool":true}
Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
Gson gson = new Gson();
Map<String, Object> map = gson.fromJson(json, mapType);

String str = (String) map.get("str"); // cannot cast Object to String
str = String.valueOf(map.get("str")); // results in java.lang.Object@1632847
}

1 Ответ

2 голосов
/ 21 сентября 2011

Технический ответ

Если вы присоедините исходный код Gson, а затем отладите программу, вы найдете источник проблемы.Кажется, проблема заключается в коде Gson.

Поскольку значение имеет тип Object, к которому вы обращаетесь из fromJson (), будет использоваться класс com.google.gson.ObjectNavigator, который входит в этот раздел кода [~ строка 113]

else if (objTypePair.type == Object.class && isPrimitiveOrString(objectToVisit)) {
   visitor.visitPrimitive(objectToVisit); //Target value is the proper value after this call
   visitor.getTarget(); //target value is now a blank Object.

где посетитель имеет тип JSonObjectDeserializationVisitor, objectToVisit - это ваше значение, а objectTypePair - это тип, которым он должен стать (Object).

Теперь у JsonObjectDeserializationVisitor есть флагВызывается построенный, который по умолчанию имеет значение false.поэтому, когда вызывается метод getTarget (), он проверяет, является ли созданный флаг истинным, если нет, то создает новый экземпляр объекта, который вы пытаетесь создать.поскольку созданный флаг никогда не устанавливается, вызов getTarget () возвращает пустой объект.

Вызов getTarget () в коде кажется ненужным и, по-видимому, является источником проблемы.visitPrimitive выполняет правильное действие, помещая проанализированное значение в целевую переменную, которая будет передана обратно.Похоже, это ошибка, связанная с типом объекта.

Это не то, что вы можете исправить, если не хотите делать пользовательскую сборку Gson.Я бы порекомендовал подать это в виде отчета на форумах Gson.Уже один отчет подан для версии 1.5

Обход

Я вижу два способа исправить это в краткосрочной перспективе.

1) Создайте карту типа <String, String>, хотя вы потеряете типы, вы все равно сможете вернуть значения должным образом

2) Сначала поместите значения в класс компонента, а затем сериализуйте его..

public class myObj{
  String myStr;
  int    myInt;
  boolean myBool;
  //get and set methods
}

public static void main(String args[]){
   MyObj o = new MyObj();
   o.setMyStr("str-value");
   Gson gson = new Gson();
   String json = gson.toJson(o);

   o = gson.fromJson(json, MyObj.class);
}

Оба побеждают цель того, что вы пытаетесь сделать, но, как я полагаю, исправление этой ошибки происходит в суде гуглов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...