GSON не вызывает мой TypeAdapter для типа, который является интерфейсом

GSON, кажется, делает какую-то хитрость, где он смотрит на внутренние поля моего JavaBeans вместо использования общедоступной информации о свойствах. К сожалению, это не сработает для нас, потому что наши магически созданные бобы полны приватных полей, которые я не хочу, чтобы они хранили.

@Test
public void testJson() throws Exception
{
    Player player = new MagicPlayer(); //BeanUtils.createDefault(Player.class);
    player.setName("Alice");

    Gson gson = new GsonBuilder()
        .registerTypeAdapter(Player.class, new PlayerTypeAdapter())
        .create();

    System.out.println(gson.toJson(bean));
}

private static class PlayerTypeAdapter implements JsonSerializer<Player>
{
    @Override
    public JsonElement serialize(Player player, Type type,
                                 JsonSerializationContext context)
    {
        throw new RuntimeException("I got called, woohoo");
    }
}

public static interface Player //extends SupportsPropertyChanges
{
    public String getName();
    public void setName(String name);
}

// Simple implementation simulating what we're doing.
public static class MagicPlayer implements Player
{
    private final String privateStuff = "secret";
    private String name;

    @Override
    public String getName()
    {
        return name;
    }

    @Override
    public void setName(String name)
    {
        this.name = name;
    }
}

Это дает:

{"privateStuff":"secret","name":"Alice"}

И, конечно же, никогда не вызывает мой тип адаптера, который, по-видимому, делает невозможным другое поведение.

 Jesse Wilson18 мая 2012 г., 07:31
Не могли бы вы добавить код, который вызывает Gson.toJson ()?
 dimo41420 апр. 2014 г., 07:09
Не ясно, что это та же проблема, но я столкнулся с чем-то похожим некоторое время назад, возможно, это поможет вам:stackoverflow.com/questions/5952595/…

Ответы на вопрос(3)

У меня была такая же проблема, с версией 2.3.1 Gson. Я получил это с помощью

.registerTypeHierarchyAdapter(Player.class, new PlayerTypeAdapter())

вместо

.registerTypeAdapter(Player.class, new PlayerTypeAdapter())
 13 окт. 2015 г., 16:35
Этот должен быть принят в качестве ответа. Работает с java.util.Calendar (фактический тип - java.util.GregorianCalendar)

Почему это не работает:

PlayerTypeAdapter should implements JsonSerializer. Does it?

If it does - than should work. It work perfect for me, so don't see reason why it does not work for you. Start you application in debug, put breakpoints and checkout. There should be some reason.

В вашем тесте, где Gson строитель с адаптером? Вы должны изменить это:

public void testJson() throws Exception
{
    Player player = new MagicPlayer(); //BeanUtils.createDefault(Player.class);
    player.setName("Alice");

    // this is wrong if you want adapter
    /* Gson gson = new Gson(); */

    // this is what you nead
     Gson gson = new GsonBuilder()
        .registerTypeAdapter(Player.class, new PlayerTypeAdapter())
        .create();

    System.out.println(gson.toJson(bean));
}
 Trejkaz18 мая 2012 г., 00:27
В приведенном выше вопросе вы можете увидеть, как реализован PlayerTypeAdapter. Я ставлю точку останова на строку, где я выкидываю исключение, но эта линия никогда не достигается. Ergo, Gson не звонит моему сериализатору. Должно быть что-то еще, что я должен сделать. Либо так, либо Gson не вызывает адаптеры типа для интерфейсов (это просто означает, что я не могу его использовать).
 Trejkaz21 мая 2012 г., 01:53
Пожалуйста, прочитайте вопрос, прежде чем обновлять свой ответ дальше.
 Trejkaz18 мая 2012 г., 00:35
Хорошо, обновлено, чтобы удалить CGLIB из уравнения. Gson до сих пор не вызывает мой адаптер типа в любой момент.

Текущая версия GSON не работает таким образом. Это позволит сериализовать ваш тип с помощью адаптера.

gson.toJson(bean, Player.class)

В качестве альтернативы вы можете зарегистрироватьPlayerTypeAdapter заMagicPlayer.class и ваш существующий код будет работать. GSON смотрит вверхTypeAdapter только по конкретному (или верхнему уровню) типу. Таким образом, вам придется зарегистрировать специальный адаптер для каждого конкретного типа, с которым вы можете столкнуться.

ЕстьTypeHeirarchyAdapter когда хочешь того жеTypeAdapter использоваться для всех расширяющихся классов данного типа. Хотя мне не повезло с этим, и я действительно не тратил время на то, чтобы понять, почему это не сработало для меня. Вот некоторые соответствующие обсуждения:https://groups.google.com/forum/?fromgroups=#!searchin/google-gson/interface/google-gson/0ebOxifqwb0/OXSCNTiLpBQJ

 26 авг. 2012 г., 19:58
Вторая часть вопроса объясняет, что делать. Для каждого конкретного типа вам необходимо зарегистрироватьTypeAdapter Вы хотите использовать.
 Trejkaz24 авг. 2012 г., 06:32
Это отвечает на основную часть вопроса о том, почему это не работает. Это точно не решает проблему и не делает GSON пригодным для использования каким-либо образом, потому что полагаться на код, сообщающий ему тип всего, никогда не будет работать. например, в другом месте у меня есть список & lt; Object & gt; где каждый объект может быть любого типа. Что мне теперь делать?

Ваш ответ на вопрос