如何使用 Jackson dataformat.xml 序列化 java 中的 LookAndFeel 对象?
How to use Jackson dataformat.xml to serialize a LookAndFeel object in java?
在Java JDK 14.0.1,
当我尝试序列化时:
private LookAndFeel lookAndFeel = new FlatLightLaf();
// I am obviously creating this in a working object as the serializing in xml with jackson has been successful until this specific object was added.
它正在使用 https://www.formdev.com/flatlaf/ 作为 maven 依赖项存储。
使用我的 pom.xml 中的 com.fasterxml.jackson.dataformat.xml
和我听说的 com.fasterxml.woodstox-core
可以防止某些错误:
<dependency>
<groupId>com.formdev</groupId>
<artifactId>flatlaf</artifactId>
<version>0.36</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
<version>5.1.0</version>
</dependency>
具有以下序列化功能:
public void serializeSettings(Settings settings, File directoryToStore) {
XmlMapper xmlMapper = new XmlMapper();
try {
xmlMapper.writeValue(directoryToStore, settings);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
它正在使用一个设置对象(我将提供的不是完整的对象,只是一个尽可能小的表示是什么变量导致了这个问题,请记住我已经删除或缩短了大部分 java doc 使其更短阅读):
Settings.java
package com.pygame_studio.settings;
import java.io.File;
import javax.swing.LookAndFeel;
import com.pygame_studio.settings.appearance_and_behavior.AppearanceAndBehavior;
public class Settings {
private File storedSettingsFile; // Where the settings .xml file is stored.
private AppearanceAndBehavior appearanceAndBehavior; // Stores all the settings to do with the appearance and behavior of Pygame Studio.
public Settings() {
super();
}
public Settings(File storedSettingsFile,
/*Appearance And Behavior settings*/
LookAndFeel lookAndFeel) {
this.setStoredSettingsFile(storedSettingsFile);
this.setAppearanceAndBehavior(new AppearanceAndBehavior(lookAndFeel));
}
public Settings(File storedSettingsFile,
AppearanceAndBehavior appearanceAndBehavior) {
this.setStoredSettingsFile(storedSettingsFile);
this.setAppearanceAndBehavior(appearanceAndBehavior);
}
/**
* @return storedSettingsFile
*/
public File getStoredSettingsFile() {
return storedSettingsFile;
}
/**
* @param storedSettingsFile - storedSettingsFile to set.
*/
public void setStoredSettingsFile(File storedSettingsFile) {
this.storedSettingsFile = storedSettingsFile;
}
/**
* @return appearanceAndBehavior
*/
public AppearanceAndBehavior getAppearanceAndBehavior() {
return appearanceAndBehavior;
}
/**
* @param appearanceAndBehavior - appearanceAndBehavior to set.
*/
public void setAppearanceAndBehavior(AppearanceAndBehavior appearanceAndBehavior) {
this.appearanceAndBehavior = appearanceAndBehavior;
}
}
AppearanceAndAppearance.java
package com.pygame_studio.settings.appearance_and_behavior;
import java.io.File;
import javax.swing.LookAndFeel;
public class AppearanceAndBehavior {
private LookAndFeel lookAndFeel; // Stores the look and feel of the program.
public AppearanceAndBehavior() {
super();
}
public AppearanceAndBehavior(LookAndFeel lookAndFeel) {
this.setLookAndFeel(lookAndFeel);
}
/**
* @return - lookAndFeel
*/
public LookAndFeel getLookAndFeel() {
return this.lookAndFeel;
}
/**
* @param lookAndFeel - lookAndFeel to set
*/
public void setLookAndFeel(LookAndFeel lookAndFeel) {
this.lookAndFeel = lookAndFeel;
}
}
我收到以下错误:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.formdev.flatlaf.UIDefaultsLoader$$Lambda/0x0000000800c2f040 and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.pygame_studio.settings.Settings["appearanceAndBehavior"]->com.pygame_studio.settings.appearance_and_behavior.AppearanceAndBehavior["lookAndFeel"]->com.formdev.flatlaf.FlatLightLaf["defaults"]->javax.swing.UIDefaults["CheckBoxMenuItem.border"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1277)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:726)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithoutTypeInfo(MapSerializer.java:681)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:637)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:33)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializerBase.serializeFields(XmlBeanSerializerBase.java:212)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializer.serialize(XmlBeanSerializer.java:129)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializerBase.serializeFields(XmlBeanSerializerBase.java:212)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializer.serialize(XmlBeanSerializer.java:129)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializerBase.serializeFields(XmlBeanSerializerBase.java:212)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializer.serialize(XmlBeanSerializer.java:129)
at com.fasterxml.jackson.dataformat.xml.ser.XmlSerializerProvider.serializeValue(XmlSerializerProvider.java:109)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:4374)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:3570)
at com.pygame_studio.settings.SettingsManager.serializeSettings(SettingsManager.java:41)
at com.pygame_studio.PygameStudio.<init>(PygameStudio.java:24)
at com.pygame_studio.PygameStudio.main(PygameStudio.java:31)
我知道“CheckBoxMenuItem.border”可能没有 public getter 和 setter 由于我对这个错误所做的研究,但我没有我想我可以改变这个。
我尝试了以下解决方案:Serializing with Jackson (JSON) - getting "No serializer found"?
放置:xmlMapper.setVisibility(javax.swing.UIDefaults.CheckBoxMenuItem.border.FIELD, Visibility.ANY);
初始化 xmlMapper 后直接。
但是这会产生一个错误,指出 CheckBoxMenuItem
属性不存在。
为什么会出现 No serializer found
错误?
如何解决?
编辑:按照建议我在 serializeSettings()
方法中尝试了 xmlMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
但是我收到了以下警告:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.fasterxml.jackson.databind.util.ClassUtil (file:/C:/Users/Eno/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.11.1/jackson-databind-2.11.1.jar) to method sun.awt.SunHints$Value.getIndex()
WARNING: Please consider reporting this to the maintainers of com.fasterxml.jackson.databind.util.ClassUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
此外,当我尝试反序列化它们时,我遇到了更多的错误,所以我认为这行不通。
不要尝试序列化 class FlatLightLaf(或任何其他 LookAndFeel class)。它不是设计为可序列化的,这样做是没有意义的。我是 FlatLaf 的作者。
而是使用外观的 class 名称(作为字符串)。
序列化使用:
String className = UIManager.getLookAndFeel().getClass().getName();
// write look and feel class name
反序列化使用:
String className = ... // read look and feel class name
UIManager.setLookAndFeel( className );
在Java JDK 14.0.1,
当我尝试序列化时:
private LookAndFeel lookAndFeel = new FlatLightLaf();
// I am obviously creating this in a working object as the serializing in xml with jackson has been successful until this specific object was added.
它正在使用 https://www.formdev.com/flatlaf/ 作为 maven 依赖项存储。
使用我的 pom.xml 中的 com.fasterxml.jackson.dataformat.xml
和我听说的 com.fasterxml.woodstox-core
可以防止某些错误:
<dependency>
<groupId>com.formdev</groupId>
<artifactId>flatlaf</artifactId>
<version>0.36</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
<version>5.1.0</version>
</dependency>
具有以下序列化功能:
public void serializeSettings(Settings settings, File directoryToStore) {
XmlMapper xmlMapper = new XmlMapper();
try {
xmlMapper.writeValue(directoryToStore, settings);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
它正在使用一个设置对象(我将提供的不是完整的对象,只是一个尽可能小的表示是什么变量导致了这个问题,请记住我已经删除或缩短了大部分 java doc 使其更短阅读):
Settings.java
package com.pygame_studio.settings;
import java.io.File;
import javax.swing.LookAndFeel;
import com.pygame_studio.settings.appearance_and_behavior.AppearanceAndBehavior;
public class Settings {
private File storedSettingsFile; // Where the settings .xml file is stored.
private AppearanceAndBehavior appearanceAndBehavior; // Stores all the settings to do with the appearance and behavior of Pygame Studio.
public Settings() {
super();
}
public Settings(File storedSettingsFile,
/*Appearance And Behavior settings*/
LookAndFeel lookAndFeel) {
this.setStoredSettingsFile(storedSettingsFile);
this.setAppearanceAndBehavior(new AppearanceAndBehavior(lookAndFeel));
}
public Settings(File storedSettingsFile,
AppearanceAndBehavior appearanceAndBehavior) {
this.setStoredSettingsFile(storedSettingsFile);
this.setAppearanceAndBehavior(appearanceAndBehavior);
}
/**
* @return storedSettingsFile
*/
public File getStoredSettingsFile() {
return storedSettingsFile;
}
/**
* @param storedSettingsFile - storedSettingsFile to set.
*/
public void setStoredSettingsFile(File storedSettingsFile) {
this.storedSettingsFile = storedSettingsFile;
}
/**
* @return appearanceAndBehavior
*/
public AppearanceAndBehavior getAppearanceAndBehavior() {
return appearanceAndBehavior;
}
/**
* @param appearanceAndBehavior - appearanceAndBehavior to set.
*/
public void setAppearanceAndBehavior(AppearanceAndBehavior appearanceAndBehavior) {
this.appearanceAndBehavior = appearanceAndBehavior;
}
}
AppearanceAndAppearance.java
package com.pygame_studio.settings.appearance_and_behavior;
import java.io.File;
import javax.swing.LookAndFeel;
public class AppearanceAndBehavior {
private LookAndFeel lookAndFeel; // Stores the look and feel of the program.
public AppearanceAndBehavior() {
super();
}
public AppearanceAndBehavior(LookAndFeel lookAndFeel) {
this.setLookAndFeel(lookAndFeel);
}
/**
* @return - lookAndFeel
*/
public LookAndFeel getLookAndFeel() {
return this.lookAndFeel;
}
/**
* @param lookAndFeel - lookAndFeel to set
*/
public void setLookAndFeel(LookAndFeel lookAndFeel) {
this.lookAndFeel = lookAndFeel;
}
}
我收到以下错误:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.formdev.flatlaf.UIDefaultsLoader$$Lambda/0x0000000800c2f040 and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.pygame_studio.settings.Settings["appearanceAndBehavior"]->com.pygame_studio.settings.appearance_and_behavior.AppearanceAndBehavior["lookAndFeel"]->com.formdev.flatlaf.FlatLightLaf["defaults"]->javax.swing.UIDefaults["CheckBoxMenuItem.border"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1277)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:726)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithoutTypeInfo(MapSerializer.java:681)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:637)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:33)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializerBase.serializeFields(XmlBeanSerializerBase.java:212)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializer.serialize(XmlBeanSerializer.java:129)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializerBase.serializeFields(XmlBeanSerializerBase.java:212)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializer.serialize(XmlBeanSerializer.java:129)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializerBase.serializeFields(XmlBeanSerializerBase.java:212)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializer.serialize(XmlBeanSerializer.java:129)
at com.fasterxml.jackson.dataformat.xml.ser.XmlSerializerProvider.serializeValue(XmlSerializerProvider.java:109)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:4374)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:3570)
at com.pygame_studio.settings.SettingsManager.serializeSettings(SettingsManager.java:41)
at com.pygame_studio.PygameStudio.<init>(PygameStudio.java:24)
at com.pygame_studio.PygameStudio.main(PygameStudio.java:31)
我知道“CheckBoxMenuItem.border”可能没有 public getter 和 setter 由于我对这个错误所做的研究,但我没有我想我可以改变这个。
我尝试了以下解决方案:Serializing with Jackson (JSON) - getting "No serializer found"?
放置:xmlMapper.setVisibility(javax.swing.UIDefaults.CheckBoxMenuItem.border.FIELD, Visibility.ANY);
初始化 xmlMapper 后直接。
但是这会产生一个错误,指出 CheckBoxMenuItem
属性不存在。
为什么会出现 No serializer found
错误?
如何解决?
编辑:按照建议我在 serializeSettings()
方法中尝试了 xmlMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
但是我收到了以下警告:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.fasterxml.jackson.databind.util.ClassUtil (file:/C:/Users/Eno/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.11.1/jackson-databind-2.11.1.jar) to method sun.awt.SunHints$Value.getIndex()
WARNING: Please consider reporting this to the maintainers of com.fasterxml.jackson.databind.util.ClassUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
此外,当我尝试反序列化它们时,我遇到了更多的错误,所以我认为这行不通。
不要尝试序列化 class FlatLightLaf(或任何其他 LookAndFeel class)。它不是设计为可序列化的,这样做是没有意义的。我是 FlatLaf 的作者。
而是使用外观的 class 名称(作为字符串)。
序列化使用:
String className = UIManager.getLookAndFeel().getClass().getName();
// write look and feel class name
反序列化使用:
String className = ... // read look and feel class name
UIManager.setLookAndFeel( className );