![](/img/trans.png)
[英]Java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/exc/InvalidDefinitionException
[英]Java InvalidDefinitionException when serializing object with jackson databind
我正在嘗試使用Jackson的ObjectMapper將以下Player對象編寫為String。
package models.Game;
import models.Game.Enums.SnowballState;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import java.util.ArrayList;
import java.util.List;
public class Player {
private Circle circle;
private String name;
private Color color;
private int points = 0;
public int getLives() {
return lives;
}
private int lives = 3;
private List<Snowball> snowballs;
private Circle oldCircle;
private int stepSize = 10;
public Player(String name, Color color) {
this.name = name;
circle = new Circle();
oldCircle = new Circle();
this.color = color;
snowballs = new ArrayList<>();
snowballs.add(new Snowball(this));
snowballs.add(new Snowball(this));
snowballs.add(new Snowball(this));
}
public Player() {
}
private void removeLife() {
this.lives--;
}
public int getHit() {
removeLife();
return getLives();
}
public int shotSuccess() {
points+= 50;
return points;
}
public int getSnowballAmount() {
int balls = 0;
for (Snowball ball : snowballs) {
if (ball.getState() == SnowballState.CREATED) {
balls++;
}
}
return balls;
}
public List<Snowball> getSnowballs() {
return snowballs;
}
public Snowball getNextSnowball() {
for (Snowball ball : snowballs) {
if (ball.getState() == SnowballState.CREATED) {
return ball;
}
}
return null;
}
public void createSnowball() {
if (getSnowballAmount() < 3) {
snowballs.add(new Snowball(this));
}
}
public Color getColor() {
return this.color;
}
public Circle getCircle() {
return this.circle;
}
public void moveLeft() {
saveOld();
circle.setTranslateX(circle.getTranslateX() - stepSize);
}
public void moveRight() {
saveOld();
circle.setTranslateX(circle.getTranslateX() + stepSize);
}
public void moveUp() {
saveOld();
circle.setTranslateY(circle.getTranslateY() - stepSize);
}
public void moveDown() {
saveOld();
circle.setTranslateY(circle.getTranslateY() + stepSize);
}
public void undo() {
circle.setTranslateX(oldCircle.getTranslateX());
circle.setTranslateY(oldCircle.getTranslateY());
}
private void saveOld() {
oldCircle.setTranslateX(circle.getTranslateX());
oldCircle.setTranslateY(circle.getTranslateY());
}
public Snowball shootSnowball(Snowball ball, double mouseX, double mouseY) {
double polarDirection = Math.atan2(mouseY - circle.getTranslateY(), mouseX - circle.getTranslateX() + 50);
ball.setState(SnowballState.ALIVE);
ball.setDirection(polarDirection);
ball.getCircle().setTranslateX(circle.getTranslateX() + 50);
ball.getCircle().setTranslateY(circle.getTranslateY());
return ball;
}
我正在使用以下命令執行此操作:
String json = null;
try {
json = objectMapper.writeValueAsString(instanceOfPlayerClass);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
不幸的是,我收到以下相關的錯誤消息:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException:類型
com.sun.javafx.scene.NodeEventDispatcher
類型定義無效:無法為[simple type,class com.sun.javafx.scene.NodeEventDispatcher]構造BeanSerializer:(java .lang.reflect.InaccessibleObjectException)無法使公共最終com.sun.javafx.event.BasicEventDispatcher com.sun.javafx.event.BasicEventDispatcher.getPreviousDispatcher()可訪問:模塊javafx.base不“導出com.sun.javafx。 event“to module com.fasterxml.jackson.databind(通過參考鏈:models.communication.Websockets.ConnectionSubmitModel [”player“] - > models.Game.Player [”circle“] - > javafx.scene.shape.Circle [ “父”] - > javafx.scene.layout.GridPane [ “父”] - > javafx.scene.layout.AnchorPane [ “此事件”])
就像錯誤說它與JavaFx沒有導出某種依賴關系有關,但由於我不能控制JavaFx,我不確定如何解決這個問題。
您正在嘗試存儲Circle
類,它是一個JavaFX類,它實際上不是一個數據類(它是一個UI元素),具有許多屬性(如半徑,粗細,顏色,填充,邊框等)。 因此,它以各種方式與JavaFX系統捆綁在一起,並且不能很好地存儲。
相反,只需將您想要的信息存儲在您自己的簡單類中,該類具有在您閱讀時再次創建Circle
對象所需的信息。
一般來說Jackson
在POJO
課程中表現最好。 如果要序列化業務對象,可能會發生許多意外錯誤。 可能最好的解決方案是創建代表Player
和Snowball
狀態的新模型類。 像PlayerState
和SnowballState
類的東西。 這兩個類應遵循POJO
規則: getters
, setters
, no-arg constructor
等。當您需要將狀態保存到JSON
您可以將業務模型轉換為狀態模型和序列化狀態模型 。 當您需要反序列化JSON
,需要將其反序列化為狀態模型 ,然后將其轉換為業務模型 。 對於JavaFX
類,如果需要,您需要實現自定義序列化器和解串器。 他們也不是常規的POJO
課程,需要特殊待遇。
讓我們實現兩個序列化器和一個解串器:
class CircleJsonSerializer extends JsonSerializer<Circle> {
@Override
public void serialize(Circle value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject();
gen.writeNumberField("radius", value.getRadius());
gen.writeNumberField("centerX", value.getCenterX());
gen.writeNumberField("centerY", value.getCenterY());
gen.writeEndObject();
}
}
class CircleJsonDeserializer extends JsonDeserializer<Circle> {
@Override
public Circle deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
TreeNode node = p.readValueAsTree();
NumericNode radius = (NumericNode) node.get("radius");
NumericNode centerX = (NumericNode) node.get("centerX");
NumericNode centerY = (NumericNode) node.get("centerY");
return new Circle(centerX.doubleValue(), centerY.doubleValue(), radius.doubleValue());
}
}
class ColorJsonDeserializer extends JsonDeserializer<Color> {
@Override
public Color deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
TreeNode node = p.readValueAsTree();
NumericNode red = (NumericNode) node.get("red");
NumericNode green = (NumericNode) node.get("green");
NumericNode blue = (NumericNode) node.get("blue");
NumericNode opacity = (NumericNode) node.get("opacity");
return Color.color(red.doubleValue(), green.doubleValue(), blue.doubleValue(), opacity.doubleValue());
}
}
你可以使用它們如下:
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.NumericNode;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
Player player = new Player("N1", Color.BLUE);
SimpleModule javafxModule = new SimpleModule();
javafxModule.addSerializer(Circle.class, new CircleJsonSerializer());
javafxModule.addDeserializer(Circle.class, new CircleJsonDeserializer());
javafxModule.addDeserializer(Color.class, new ColorJsonDeserializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(javafxModule);
mapper.enable(SerializationFeature.INDENT_OUTPUT);
String json = mapper.writeValueAsString(player);
System.out.println(json);
System.out.println(mapper.readValue(json, Player.class));
}
}
上面的代碼打印:
{
"circle" : {
"radius" : 1.0,
"centerX" : 0.0,
"centerY" : 0.0
},
"color" : {
"red" : 0.0,
"green" : 0.0,
"blue" : 1.0,
"opacity" : 1.0,
"opaque" : true,
"hue" : 240.0,
"saturation" : 1.0,
"brightness" : 1.0
},
"lives" : 3,
"snowballs" : [ {
"state" : "CREATED",
"direction" : 0.0,
"circle" : null
}, {
"state" : "CREATED",
"direction" : 0.0,
"circle" : null
}, {
"state" : "CREATED",
"direction" : 0.0,
"circle" : null
} ]
}
//ToString
Player{circle=Circle[centerX=0.0, centerY=0.0, radius=1.0, fill=0x000000ff], name='null', color=0x0000ffff, points=0, lives=3, snowballs=[Snowball{player=null, state=CREATED, direction=0.0, circle=null}, Snowball{player=null, state=CREATED, direction=0.0, circle=null}, Snowball{player=null, state=CREATED, direction=0.0, circle=null}], oldCircle=null, stepSize=10}
正如您所看到的,我們可以序列化和反序列化Player
類,但它需要許多額外的工作。 對於執行業務邏輯的每個getter
方法,我也忽略了它們,如下所示:
@JsonIgnore
public int getHit() {
removeLife();
return getLives();
}
還有一個提示: getHint
方法有副作用。 它消除了生命 - 無論它意味着什么。 這通常是一種不好的做法,但這個問題與命名無關。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.