десериализовать обобщенную хэш-карту, когда ключ не является примитивным - PullRequest
1 голос
/ 27 марта 2011

Я хочу, чтобы gson и de-gson создали хэш-карту с шаблонами.
Я могу сделать это успешно, когда мой ключ - строка, но не если это объект.
У меня есть две части кода здесь.первое не работает, а второе работает.

// doesnt work works
 try {
       TradableBean tradable = new TradableBean("Tradable");
       PositionBean position = new PositionBean(tradable);
       Map<TradableBean, PositionBean> map1 = new HashMap<TradableBean, PositionBean>();
       map1.put(tradable, position);
       String json1 = gson.toJson(map1);
       Map<TradableBean, PositionBean> map2 = gson.fromJson(json1, new TypeToken<Map<TradableBean, PositionBean>>(){}.getType());
       System.out.println(map2);
   } catch (Exception e) {
       System.out.println("failed");
   }

и теперь рабочая часть -

 // works - with string
   try {
       String tradable = new String("Tradable");
       PositionBean position = new PositionBean(new TradableBean("Tradable"));
       Map<String, PositionBean> map1 = new HashMap<String,PositionBean>();
       map1.put(tradable, position);
       String json1 = gson.toJson(map1);
       Map<String, PositionBean> map2 = gson.fromJson(json1, new TypeToken<Map<String, PositionBean>>() {}.getType());
       System.out.println(map2);
   } catch (Exception e) {
       System.out.println("failed");
   }

, а в TradableBean у меня есть:

@Override public int hashCode() {
   return getId();} 
@Override public boolean equals(Object obj) {
   boolean equals = false;
   if (obj instanceof AccountBean){
       TradableBean tradable_p = (TradableBean)obj;
       if (getId()==tradable_p.getId()){
           equals = true;
       }
   }
   return equals;

}

исключение:

com.google.gson.JsonParseException: Expecting object found:
"TradableBean{id=0, tradableName='Tradable', moneyMultiplier=1,
expirationDate=null}"
       at
com.google.gson.JsonObjectDeserializationVisitor.visitFieldUsingCustomHandler(JsonObjectDeserializationVisitor.java:
100)
       at
com.google.gson.ObjectNavigator.navigateClassFields(ObjectNavigator.java:
150)
       at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:123)
       at
com.google.gson.JsonDeserializationContextDefault.fromJsonPrimitive(JsonDeserializationContextDefault.java:
84)
       at
com.google.gson.JsonDeserializationContextDefault.deserialize(JsonDeserializationContextDefault.java:
53)
       at com.google.gson.DefaultTypeAdapters
$MapTypeAdapter.deserialize(DefaultTypeAdapters.java:531)
       at com.google.gson.DefaultTypeAdapters
$MapTypeAdapter.deserialize(DefaultTypeAdapters.java:498)
       at
com.google.gson.JsonDeserializerExceptionWrapper.deserialize(JsonDeserializerExceptionWrapper.java:
50)

Ответы [ 2 ]

2 голосов
/ 10 июня 2011

Ответ Дэна на правильном пути.

Ограничение Gson, с которым вы сталкиваетесь, касается того, как он в настоящее время сериализует ключи карты: вызывая toString(). От MapTypeAdapter:

map.add(String.valueOf(entry.getKey()), valueElement);

Это поведение также описано в документации MapTypeAdapter.

Эта реализация действительно хорошо работает только с простыми примитивными типами в качестве ключа карты. Если ключ не является простым примитивом, тогда объект {@code toString} ed и это значение используется в качестве его ключа.

Если вы настаиваете на использовании пользовательских типов в качестве ключей карты, то, насколько я могу сказать, вам придется написать собственный сериализатор и / или пользовательский десериализатор и / или toString(), который генерирует строковое представление, которое легко десериализовать.

Кроме того, взгляните на MapAsArrayTypeAdapter для одного подхода. (Его можно использовать с вызовом GsonBuilder.enableComplexMapKeySerialization(), а не с помощью прямой реализации, как описано в документации (потому что в настоящее время это не публичный класс). Я не проверял его, чтобы убедиться, что его реализация работает, но он выглядит многообещающим.) *

1 голос
/ 27 марта 2011

Я думаю, вам нужно написать свой собственный пользовательский сериализатор .

Обновление: Контрольный сигнал - исключение:

com.google.gson.JsonParseException: Expecting object found: "TradableBean{id=0, tradableName='Tradable', moneyMultiplier=1, expirationDate=null}"

Предположительная строка «TradableBean», кажется, написана сериализацией, которая использует некоторый вид toString(). Десериализация ожидаемого объекта вида {id=0,... }

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