当前位置: 首页 > 知识库问答 >
问题:

使用jackson数据绑定序列化对象时发生Java InvalidDefinitionException

东门宜
2023-03-14

我正在尝试使用Jackson的ObjectMapper将以下Player对象编写为字符串。

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();
        }

不幸的是,我收到以下相关错误消息:

通用域名格式。fasterxml。杰克逊。数据绑定。exc.InvalidDefinitionException:类型com的类型定义无效。太阳javafx。场景NodeEventDispatcher:无法为[simple type,class com.sun.javafx.scene.NodeEventDispatcher]构造BeanSerializer:(java.lang.reflect.InAccessibleObject异常)无法公开最终com。太阳javafx。事件BasicEventDispatcher公司。太阳javafx。事件基本喷灯。getPreviousDispatcher()可访问:模块javafx。base不会“导出com.sun.javafx.event”到模块com。fasterxml。杰克逊。数据绑定(通过引用链:models.communication.Websockets.ConnectionSubmitModel[“player”]-

就像这个错误说它与JavaFx没有导出某个依赖项有关,但是因为我不能控制JavaFx,所以我不确定如何修复这个问题。

共有2个答案

丁弘新
2023-03-14

一般来说,Jackson最适合POJO类。当您想要序列化业务对象时,可能会发生许多意外错误。最好的解决方案可能是创建新的模型类,它表示PlayerSnowball的状态。类似于PlayerStateSnowballState。这两个类应该遵循POJO规则:getterssettersno-arg构造函数,等等。当您需要将状态保存到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方法有副作用。它剥夺了生命——不管它意味着什么。这通常是一种不好的做法,但这个问题与命名无关。

郭琦
2023-03-14

您试图存储的Circle类是一个JavaFX类,它不是一个真正的数据类(它是一个UI元素),具有许多属性(如半径、厚度、颜色、填充、边框等)。因此,它以各种方式与JavaFX系统联系在一起,不会很好地存储

相反,只需将所需信息存储在自己的一个简单类中,该类包含在读回时再次创建圆圈对象所需的信息。

 类似资料:
  • 我有一个非常大的JSON文件太大,无法使用ObjectMapper.read值()到JsonNode的问题。我想在Android上使用杰克逊库解析大型JSON时使用内存不足错误的解决方案,除了JSON文件是一个具有字段名称的单个对象,因此我无法创建一个模型POJO来反序列化。 对象内部的每个属性都有相同的格式,我可以忽略这些内部对象的许多属性(我已经有了一个POJO类来建模)。如果JSON文件是一

  • 我所在的团队使用杰克逊数据绑定来处理发送到 REST API 和从 REST API 发送的 JSON 的序列化和反序列化。该 API 广泛使用一种臭名昭著且难以处理的模式,我们称之为“键值”。不幸的是,JSON的格式超出了我们的控制范围,所以我试图找到一种简单易行的好方法来处理序列化和反序列化它们。 键值总是以下列模式出现: 值得注意的是,它们始终采用数组的形式,其中包含单个对象,并且对象中 k

  • 主要内容:1 编写核心类,2 运行测试本文讲解如何将一个Java对象序列化为一个json文件,然后读取该json文件读取回对象。在下面的示例中,我们创建Student类。使用Jackson存储到一个student.json文件,该文件拥有Student对象的JSON表示形式。 1 编写核心类 MainApp: 2 运行测试

  • 我目前正在开发一个Java web应用程序,它使用Magento REST API公开的JSON数据。api返回的数据示例如下: 我的应用程序中有一个Java类,如下所示: 我想对数据进行反序列化,并将其转换为,但我总是得到以下错误: 这是我用来将JSON响应反序列化为ArrayList的语句行: 有人能分享一些见解吗?我看到一些例子,返回的JSON对象前面没有任何ID。那是因为我做错了什么吗?非

  • 是否可以在Jackson中只使用注释序列化没有字段的对象?当我尝试序列化这样一个没有注释的对象时,我得到: 我检查了Jackson注释列表,但没有看到将类注释为没有可序列化数据的方法。我尝试将放在空构造函数上(不希望它工作,因为它是一个反序列化注释),但我得到了同样的错误。没有可将放置在其上的访问器或字段。有什么想法吗? 更新:这样做的原因是我有一个对象列表,这些对象表示可以应用于某种类型的数据的

  • 我有下面的JSON,我正试图使用Jackson API反序列化它 我基本上需要一个附件类,它有一个AttachmentFile对象列表,如下所示: 如何使用自定义反序列化器实现这一点? 谢谢