Java stati c переменные не инициализируются при десериализации xml с использованием Джексона - PullRequest
1 голос
/ 21 июня 2020

У меня возникла проблема при попытке десериализации xml с помощью jackson.

Я использую следующую функцию для десериализации моего xml из файла.

Файл Xml выглядит как -:

https://github.com/Eno-Gerguri/Pygame-Studio/blob/master/Settings/defaultSettings.xml

Вот функция, которую я использую для десериализации объекта:

    public Settings deserializeSettings(File settingsFile) {
        XmlMapper xmlMapper = new XmlMapper();
        String xml = null;
        Settings settings = null;
        
        try {
            xml = inputStreamToString(new FileInputStream(settingsFile));
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            
        } catch (IOException e) {
            e.printStackTrace();
            
        }
        try {
            settings = xmlMapper.readValue(xml, Settings.class);
            
        } catch (JsonMappingException e) {
            e.printStackTrace();
            
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            
        }
        
        return settings;
    }
    
    private String inputStreamToString(InputStream inputStream) throws IOException {
        StringBuilder stringBuilder = new StringBuilder();
        String line;
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        while ((line = bufferedReader.readLine()) != null) {
            stringBuilder.append(line);
        }
        bufferedReader.close();
        return stringBuilder.toString();
    }

Объект настроек Я использую это десериализацию в: -

https://github.com/Eno-Gerguri/Pygame-Studio/blob/master/src/com/pygame_studio/settings/Settings.java

Подкласс, который использует объект Settings:

https://github.com/Eno-Gerguri/Pygame-Studio/blob/master/src/com/pygame_studio/settings/appearance_and_behavior/AppearanceAndBehavior.java

Подкласс, который использует объект настроек:

https://github.com/Eno-Gerguri/Pygame-Studio/blob/master/src/com/pygame_studio/settings/appearance_and_behavior/Font.java

Когда я пытаюсь десериализовать объект в отдельный файл:

private Settings defaultSettings = settingsManager.deserializeSettings(DefaultSettings.DEFAULT_SETTINGS_FILE_DIRECTORY);

Следующий журнал ошибок

com.fasterxml.jackson.databind.JsonMappingException: N/A
 at [Source: (StringReader); line: 1, column: 356] (through reference chain: com.pygame_studio.settings.Settings["appearanceAndBehavior"]->com.pygame_studio.settings.appearance_and_behavior.AppearanceAndBehavior["font"]->com.pygame_studio.settings.appearance_and_behavior.Font["fontDirectory"])
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:278)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:611)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:599)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:143)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4202)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3205)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3173)
    at com.pygame_studio.settings.SettingsManager.deserializeSettings(SettingsManager.java:75)
    at com.pygame_studio.start_menu.StartMenu.<init>(StartMenu.java:24)
    at com.pygame_studio.PygameStudio.<init>(PygameStudio.java:18)
    at com.pygame_studio.PygameStudio.main(PygameStudio.java:25)
Caused by: java.lang.NullPointerException
    at com.pygame_studio.settings.appearance_and_behavior.Font.setFontDirectory(Font.java:115)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:141)
    ... 15 more

Я знаю, что в функции: com.pygame_studio.settings.appearance_and_behavior.Font.setFontDirectory

public void setFontDirectory(String fontDirectory) {
        if (externalFonts.containsKey(fontDirectory)) {
            this.fontDirectory = externalFonts.get(fontDirectory);
        } else if (localFonts.contains(fontDirectory)) {
            this.fontDirectory = fontDirectory;
        } else {
            this.fontDirectory = this.getFallbackFont();
        }
    }

externalFonts Hashtable имеет значение null, потому что он не был инициализирован, однако он должен быть таким, как в конструкторе:

    public Font() {
        super();
    }
    
    public Font(File externalFontDirectory, String fontName, int fontStyle, int fontSize, String fallbackFont) {
        this.setExternalFontDirectory(externalFontDirectory);
        
        this.setExternalFonts();  // External fonts is set before the font directory.
        this.setLocalFonts();
        
        this.setFontDirectory(fontName);  // Font directory being set after externalFonts.
        
        this.setFontStyle(fontStyle);
        
        this.setFontSize(fontSize);
        
        this.setFallbackFont(fallbackFont);
    }

метод setExternalFonts:

    public void setExternalFonts() {
        externalFonts = getExternalFonts(this.externalFontDirectory);
    }

Метод getExternalFonts:

    public static Hashtable<String, String> getExternalFonts(File externalFontDirectory) {
        Hashtable<String, String> externalFonts = new Hashtable<>();
        
        final File[] directoryFiles = externalFontDirectory.listFiles();
        
        if (directoryFiles != null) {
            for (File file : directoryFiles) {
                if (file.isDirectory()) {  // If the file is a sub-directory.
                    externalFonts.putAll(getExternalFonts(file));  // Calls itself onto the directory.
                } else if (file.getName().contains(".ttf")) {  // If the file is a font.
                    String fontName = file.getName().replace(".ttf", "");  // Gets the name of the font.
                    externalFonts.put(fontName, file.getPath());  // Puts the, name of the font : font's directory, into the Hashtable.
                }
            }
        }
        return externalFonts;
    }

Однако моя среда IDE Eclipse сообщает мне, что этот код никогда не достигается, тогда как он должен инициализировать externalFonts.

Почему этот метод не зовут? Как мне исправить эту проблему, чтобы я мог успешно десериализовать xml в объект «Настройки»?

Заранее спасибо!

1 Ответ

1 голос
/ 23 июня 2020

Специфическая проблема c находится здесь, в классе Font:

public static Hashtable<String, String> externalFonts;

Сначала я бы рекомендовал изменить это с Hashtable на HashMap - в наши дни нет причин (в мой опыт), чтобы использовать Hashtable поверх любого из более современных классов коллекций. Вы можете прочитать мнения сообщества здесь .

Во-вторых, поле необходимо инициализировать, чтобы оно не было нулевым - как вы делаете для списка localFonts.

Это дает нам следующее:

public static Map<String, String> externalFonts = new HashMap();

Вам, конечно же, нужно будет заменить оставшиеся ссылки на Hashtable.

Когда я внес это изменение, оно исправило специфику c проблема, о которой вы сообщили.

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