Java 使用 jackson 反序列化 xml 时静态变量未被初始化
Java static variables not being initialised when deserialising xml using jackson
我在尝试使用 jackson 反序列化 xml 时遇到问题。
我正在使用以下函数从文件中反序列化我的 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();
}
我正在使用的设置对象,我正在反序列化为:-
Settings对象使用的子class:
Settings对象使用的sub-class:
当我尝试在单独的文件中反序列化对象时:
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 是空的,因为它还没有被初始化但是,它应该和构造函数中一样:
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);
}
设置外部字体方法:
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 告诉我,这段代码从未到达,而应该初始化外部字体。
为什么这个方法没有被调用?
我该如何解决这个问题,以便我可以成功地将 xml 反序列化为“设置”对象?
提前致谢!
具体问题在Font
class这里:
public static Hashtable<String, String> externalFonts;
首先,我建议将其从 Hashtable
更改为 HashMap
- 现在(根据我的经验)没有理由使用 Hashtable
而不是任何更现代的 collection classes。您可以阅读社区意见 here。
其次,该字段需要初始化,因此它不为空 - 就像您对 localFonts
列表所做的那样。
所以这给了我们这个:
public static Map<String, String> externalFonts = new HashMap();
当然,您随后需要替换对 Hashtable
的其余引用。
当我进行更改时,它解决了您报告的具体问题。
我在尝试使用 jackson 反序列化 xml 时遇到问题。
我正在使用以下函数从文件中反序列化我的 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();
}
我正在使用的设置对象,我正在反序列化为:-
Settings对象使用的子class:
Settings对象使用的sub-class:
当我尝试在单独的文件中反序列化对象时:
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 是空的,因为它还没有被初始化但是,它应该和构造函数中一样:
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);
}
设置外部字体方法:
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 告诉我,这段代码从未到达,而应该初始化外部字体。
为什么这个方法没有被调用? 我该如何解决这个问题,以便我可以成功地将 xml 反序列化为“设置”对象?
提前致谢!
具体问题在Font
class这里:
public static Hashtable<String, String> externalFonts;
首先,我建议将其从 Hashtable
更改为 HashMap
- 现在(根据我的经验)没有理由使用 Hashtable
而不是任何更现代的 collection classes。您可以阅读社区意见 here。
其次,该字段需要初始化,因此它不为空 - 就像您对 localFonts
列表所做的那样。
所以这给了我们这个:
public static Map<String, String> externalFonts = new HashMap();
当然,您随后需要替换对 Hashtable
的其余引用。
当我进行更改时,它解决了您报告的具体问题。