为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕田峪7331174 2022-12-15 11:22:23
我正在尝试使用 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);}
查看完整描述

2 回答

?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

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

相反,只需将您想要的信息存储在您自己的一个简单类中,Circle当您读回它时,它具有您再次创建对象所需的信息。


查看完整回答
反对 回复 2022-12-15
?
繁星淼淼

TA贡献1775条经验 获得超11个赞

通常在课堂Jackson上效果最好。POJO当您想要序列化业务对象时,可能会发生许多意外错误。可能最好的解决方案是创建代表和状态的新模型类。和之类的东西。这两个类应该遵循规则:, , , 等。当你需要保存状态时,你可以将你的业务模型转换为状态模型并序列化状态模型。当您需要反序列化时,您需要将其反序列化为状态模型,然后再将其转换为业务模型。为了PlayerSnowballPlayerStateSnowballStatePOJOgetterssettersno-arg constructorJSONJSONJavaFX如果需要,您需要实现自定义序列化器和反序列化器的类。他们也不是正规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方法有副作用。它消除了生命——不管它意味着什么。这通常是一种不好的做法,但这个问题与命名无关。


查看完整回答
反对 回复 2022-12-15
  • 2 回答
  • 0 关注
  • 129 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号