使用 jackson 数据绑定序列化对象时出现 Java InvalidDefinition

我正在尝试使用 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);

}



慕田峪7331174
浏览 185回答 2
2回答

米琪卡哇伊

您正在尝试存储Circle类,它是一个 JavaFX 类,它实际上不是一个数据类(它是一个 UI 元素),具有许多属性(如半径、厚度、颜色、填充、边框等)。因此,它以各种方式与 JavaFX 系统捆绑在一起,并且不会很好地存储。相反,只需将您想要的信息存储在您自己的一个简单类中,Circle当您读回它时,它具有您再次创建对象所需的信息。

繁星淼淼

通常在课堂Jackson上效果最好。POJO当您想要序列化业务对象时,可能会发生许多意外错误。可能最好的解决方案是创建代表和状态的新模型类。和之类的东西。这两个类应该遵循规则:, , , 等。当你需要保存状态时,你可以将你的业务模型转换为状态模型并序列化状态模型。当您需要反序列化时,您需要将其反序列化为状态模型,然后再将其转换为业务模型。为了PlayerSnowballPlayerStateSnowballStatePOJOgetterssettersno-arg constructorJSONJSONJavaFX如果需要,您需要实现自定义序列化器和反序列化器的类。他们也不是正规POJO班级,需要特殊对待。让我们实现两个序列化器和一个反序列化器:class CircleJsonSerializer extends JsonSerializer<Circle> {&nbsp; &nbsp; @Override&nbsp; &nbsp; public void serialize(Circle value, JsonGenerator gen, SerializerProvider serializers) throws IOException {&nbsp; &nbsp; &nbsp; &nbsp; gen.writeStartObject();&nbsp; &nbsp; &nbsp; &nbsp; gen.writeNumberField("radius", value.getRadius());&nbsp; &nbsp; &nbsp; &nbsp; gen.writeNumberField("centerX", value.getCenterX());&nbsp; &nbsp; &nbsp; &nbsp; gen.writeNumberField("centerY", value.getCenterY());&nbsp; &nbsp; &nbsp; &nbsp; gen.writeEndObject();&nbsp; &nbsp; }}class CircleJsonDeserializer extends JsonDeserializer<Circle> {&nbsp; &nbsp; @Override&nbsp; &nbsp; public Circle deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {&nbsp; &nbsp; &nbsp; &nbsp; TreeNode node = p.readValueAsTree();&nbsp; &nbsp; &nbsp; &nbsp; NumericNode radius = (NumericNode) node.get("radius");&nbsp; &nbsp; &nbsp; &nbsp; NumericNode centerX = (NumericNode) node.get("centerX");&nbsp; &nbsp; &nbsp; &nbsp; NumericNode centerY = (NumericNode) node.get("centerY");&nbsp; &nbsp; &nbsp; &nbsp; return new Circle(centerX.doubleValue(), centerY.doubleValue(), radius.doubleValue());&nbsp; &nbsp; }}class ColorJsonDeserializer extends JsonDeserializer<Color> {&nbsp; &nbsp; @Override&nbsp; &nbsp; public Color deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {&nbsp; &nbsp; &nbsp; &nbsp; TreeNode node = p.readValueAsTree();&nbsp; &nbsp; &nbsp; &nbsp; NumericNode red = (NumericNode) node.get("red");&nbsp; &nbsp; &nbsp; &nbsp; NumericNode green = (NumericNode) node.get("green");&nbsp; &nbsp; &nbsp; &nbsp; NumericNode blue = (NumericNode) node.get("blue");&nbsp; &nbsp; &nbsp; &nbsp; NumericNode opacity = (NumericNode) node.get("opacity");&nbsp; &nbsp; &nbsp; &nbsp; return Color.color(red.doubleValue(), green.doubleValue(), blue.doubleValue(), opacity.doubleValue());&nbsp; &nbsp; }}您可以按如下方式使用它们: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 {&nbsp; &nbsp; public static void main(String[] args) throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; Player player = new Player("N1", Color.BLUE);&nbsp; &nbsp; &nbsp; &nbsp; SimpleModule javafxModule = new SimpleModule();&nbsp; &nbsp; &nbsp; &nbsp; javafxModule.addSerializer(Circle.class, new CircleJsonSerializer());&nbsp; &nbsp; &nbsp; &nbsp; javafxModule.addDeserializer(Circle.class, new CircleJsonDeserializer());&nbsp; &nbsp; &nbsp; &nbsp; javafxModule.addDeserializer(Color.class, new ColorJsonDeserializer());&nbsp; &nbsp; &nbsp; &nbsp; ObjectMapper mapper = new ObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp; mapper.registerModule(javafxModule);&nbsp; &nbsp; &nbsp; &nbsp; mapper.enable(SerializationFeature.INDENT_OUTPUT);&nbsp; &nbsp; &nbsp; &nbsp; String json = mapper.writeValueAsString(player);&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(json);&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(mapper.readValue(json, Player.class));&nbsp; &nbsp; }}上面的代码打印:{&nbsp; "circle" : {&nbsp; &nbsp; "radius" : 1.0,&nbsp; &nbsp; "centerX" : 0.0,&nbsp; &nbsp; "centerY" : 0.0&nbsp; },&nbsp; "color" : {&nbsp; &nbsp; "red" : 0.0,&nbsp; &nbsp; "green" : 0.0,&nbsp; &nbsp; "blue" : 1.0,&nbsp; &nbsp; "opacity" : 1.0,&nbsp; &nbsp; "opaque" : true,&nbsp; &nbsp; "hue" : 240.0,&nbsp; &nbsp; "saturation" : 1.0,&nbsp; &nbsp; "brightness" : 1.0&nbsp; },&nbsp; "lives" : 3,&nbsp; "snowballs" : [ {&nbsp; &nbsp; "state" : "CREATED",&nbsp; &nbsp; "direction" : 0.0,&nbsp; &nbsp; "circle" : null&nbsp; }, {&nbsp; &nbsp; "state" : "CREATED",&nbsp; &nbsp; "direction" : 0.0,&nbsp; &nbsp; "circle" : null&nbsp; }, {&nbsp; &nbsp; "state" : "CREATED",&nbsp; &nbsp; "direction" : 0.0,&nbsp; &nbsp; "circle" : null&nbsp; } ]}//ToStringPlayer{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执行业务逻辑的方法,我都忽略了它们,如下所示:@JsonIgnorepublic int getHit() {&nbsp; &nbsp; removeLife();&nbsp; &nbsp; return getLives();}另一个提示:getHint方法有副作用。它消除了生命——不管它意味着什么。这通常是一种不好的做法,但这个问题与命名无关。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java