Gson создает исключение IllegalArgumentException для полей, которые не используются - PullRequest
2 голосов
/ 15 апреля 2020

Я пытаюсь использовать GSON в своем пользовательском интерфейсе Swing, когда я пытаюсь создать объект GSON, я получаю сообщение об ошибке с учетом класса java.applet.Applet. Странно то, что я даже не использую Applet элементы для сохранения или загрузки с использованием GSON.

Может кто-нибудь объяснить мне, что происходит?

Код ниже.

Я получаю ошибку

java.lang.IllegalArgumentException: class java.applet.Applet declares multiple JSON fields named accessibleContext

Загрузка объекта в json при нажатии кнопки:

JButton selectProfileSaveLocationButton = new JButton("Select Location");
    selectProfileSaveLocationButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            //todo create new empty profile
            JFileChooser jfc = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
            jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

            int returnValue = jfc.showSaveDialog(null);
            if (returnValue == JFileChooser.APPROVE_OPTION) {
                if (jfc.getSelectedFile().isDirectory()) {
                    profileSaveLocationTextfield.setText(jfc.getSelectedFile().getAbsolutePath());
                    try {
                        System.out.println("Saving file to: " + jfc.getSelectedFile().getAbsolutePath() + File.separatorChar + profileNameTextfield.getText() + ".json");
                        File dataFile = new File(jfc.getSelectedFile().getAbsolutePath() + File.separatorChar + profileNameTextfield.getText() + ".json");
                        //dataFile.createNewFile();
                        Data.botProfileLocation = dataFile;


                        SlayerProfile profile = newEmptyProfile(profileNameTextfield.getText());
                        String json = FryslanSlayer.gson.toJson(profile);

                        System.out.println(json);

                        FileWriter writer = new FileWriter(Data.botProfileLocation.getAbsolutePath());
                        FryslanSlayer.gson.toJson(profile, writer);

                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
});
selectProfileSaveLocationButton.setBackground(new Color(65, 105, 225));
selectProfileSaveLocationButton.setForeground(new Color(0, 0, 139));
selectProfileSaveLocationButton.setBounds(610, 274, 124, 25);
generalPanel.add(selectProfileSaveLocationButton);

Ответы [ 4 ]

0 голосов
/ 24 апреля 2020

GSON просматривает частные поля объекта при сериализации, что означает, что все частные поля суперкласса включены, и когда у вас есть поля с одинаковыми именами, он выдает ошибку.

Если есть какое-то конкретное поле, которое вы не ' Если вы хотите включить его, вы должны пометить его ключевым словом transient, например:

protected transient DontSerializeMeClass dontSerializeMeClass;

В этом случае вы можете попытаться скрыть поле availableContext, добавив его в Slayer. Я не уверен насчет остальной части вашего кода, потому что я вижу только его небольшой фрагмент, но я предполагаю, что он либо наследуется от Applet, либо объявляет переменную, которая происходит из этого семейного дерева.

Статья связанные с этим topi c можно найти здесь: класс A объявляет несколько JSON полей

private static transient AccesssibleContext accessibleContext = null;

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

Полиморфизм с gson

0 голосов
/ 24 апреля 2020

Вы столкнулись с этой проблемой, потому что у вашего класса SlayerProfile есть свойство типа Applet или ссылки на Applet в некоторой точке (оно может иметь много уровней). Это определенно не связано с наследованием, потому что Gson вызывает Object#getClass, чтобы получить тип, отображаемый в этой ошибке, чтобы он показал класс реализации.

Причина, по которой Gson не может десериализовать Applet, заключается в том, что он использует имена свойств для преобразования объекта в JSON. У JSON нет понятия иерархии, которое есть у Java, поэтому вы не можете создать JSON с такой неоднозначностью, которая имеет смысл и может быть сериализована обратно к тому же объекту. Подробнее о Gson, используя поля :

Некоторые библиотеки Json используют методы получения типа для вывода элементов Json. Мы решили использовать все поля (вплоть до иерархии наследования), которые не являются переходными, stati c или syntheti c. Мы сделали это, потому что не все классы написаны с подходящими именами. Более того, getXXX или isXXX могут быть semanti c, а не указывать свойства.

Не существует лучшего решения для этого с предоставленными вами данными. В зависимости от ваших потребностей, вы можете захотеть сделать эталонный переходный процесс Applet, создать пользовательский TypeAdapter или что-то еще более разумное в вашем случае.

0 голосов
/ 24 апреля 2020

Ваш класс SlayerProfile определен без ключевого слова static и в подклассе Applet? Если это так, он неявно имеет ссылку на подкласс Applet, поэтому Gson также пытается сериализовать этот класс, и вам нужно добавить ключевое слово static в SlayerProfile

0 голосов
/ 19 апреля 2020

Единственное объяснение, которое я могу оценить, состоит в том, что ваш класс SlayerProfile.class либо расширяет апплет, либо содержит поле, которое делает.

GSON не может обрабатывать классы с одинаковыми именами полей на нескольких уровнях иерархии классов, как в случае с классом Applet. См. , класс A объявляет несколько JSON полей для получения более подробной информации.

Без разделения вашего определения SlayerProfile трудно быть уверенным, что это проблема.

Другая вещь Мне не хватает в вашем вопросе определения того, как настроен ваш объект GSON. Возможно, эта проблема связана с неправильной настройкой вашего объекта GSON.

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