Десериализация универсального с неизвестным типом времени компиляции, где поле указывает тип - PullRequest
0 голосов
/ 27 марта 2011

Это работает, но это ужасно - есть ли лучший способ?

У меня есть универсальный класс, который в этом простом примере выглядит следующим образом

public class MsgWrapper<T> {
@Expose
private T Message;
@Expose
private String Type;
private String uri;
}

Сериализация неприятна, но тривиальна, например

Type typeToken = new TypeToken<MsgWrapper<Notice>>(){}.getType();
gson.toJson(message,typeToken);

Сервер получает JSON, который может быть либо

MsgWrapper<Notice> or MsgWrapper<Alert>

Если это уведомление, то в поле «Тип» будет указано «уведомление». Если это предупреждение, то в поле «Тип» будет указано «предупреждение»

На данный момент я реализовал пользовательский десериализатор

        public MsgWrapper deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject object = json.getAsJsonObject();
        if(object.has("Type"))
        {
            MsgWrapper msgWrapper=new MsgWrapper();
            msgWrapper.setType(object.get("Type").getAsString());
            if(msgWrapper.getType().equalsIgnoreCase("Notice"))
            {
             msgWrapper.setMessage(context.deserialize(object.get("Message"), Notice.class));
            }
            else if(msgWrapper.getType().equalsIgnoreCase("Alert"))
            {
             msgWrapper.setMessage(context.deserialize(object.get("Message"), Alert.class));   
            }
            return msgWrapper;
        }
        else
        {
            throw new JsonParseException("something is wrong...");
        }
    }
}

Это кажется очень неуклюжим и неправильным. Есть ли лучший способ?

1 Ответ

1 голос
/ 09 июня 2011

Решение, которое вы опубликовали, более или менее так же хорошо, как и полиморфная десериализация с текущим выпуском Gson.

Вы можете внести некоторые небольшие изменения, чтобы сделать настраиваемый десериализатор внешне настраиваемымВ соответствии с предложением Дэна с упоминанием об изменении использования Map<String, Deserializer>.

Вместо использования специального десериализатора, похоже, что у Gson скоро будет RuntimeTypeAdapter, доступный для более простой полиморфной десериализации.См. http://code.google.com/p/google-gson/issues/detail?id=231 для получения дополнительной информации.Даже если вы не можете использовать RuntimeTypeAdapter, он по крайней мере предоставляет пример для создания настраиваемого настраиваемого десериализатора.

Если вы можете переключать API отображения JSON, тогда я рекомендую рассмотреть Джексона, так как он работает и относительнодоступен простой полиморфный механизм десериализации.Я опубликовал несколько простых примеров на http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html.

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