>

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: Invalid type definition for type com.sun.javafx.scene.NodeEventDispatcher : [단순 유형, 클래스 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를 모듈 com.fasterxml.jackson.databind (참조 체인을 통해)로 내 보내지 않습니다 : models.communication.Websockets.ConnectionSubmitModel [ "player "]->models.Game.Player ["circle "]->javafx.scene.shape.Circle ["parent "]->javafx.scene.layout.GridPane ["parent "]->javafx.scene.layout. AnchorPane [ "eventDispatcher"])

오류와 같이 특정 종속성을 내 보내지 않는 JavaFx와 관련이 있다고 말하지만 JavaFx를 제어하지 않기 때문에이 문제를 해결하는 방법을 잘 모르겠습니다.

  • 답변 # 1

    Circle 를 저장하려고합니다.  JavaFX 클래스 인 class는 실제로 데이터 클래스 (UI 요소)가 아니며 많은 속성 (반지름, 두께, 색상, 채우기, 테두리 등)이 있습니다. 따라서 다양한 방식으로 JavaFX 시스템과 연결되어 있으며 잘 저장되지 않습니다.

    대신 원하는 정보를 간단한 클래스에 저장하십시오. 여기에는 Circle 를 만드는 데 필요한 정보가 있습니다.  당신이 그것을 다시 읽을 때 다시 개체.

  • 답변 # 2

    일반적으로 Jackson   POJO 와 함께 최고의 작품  클래스. 비즈니스 오브젝트를 직렬화하려는 경우 예기치 않은 많은 오류가 발생할 수 있습니다. 아마도 가장 좋은 해결책은 Player상태를 나타내는 새 모델 클래스를 만드는 것입니다.  그리고 Snowball . PlayerState 와 같은 것  그리고 SnowballState . 이 두 클래스는 POJO 를 따라야합니다.  규칙 : getters setters no-arg constructor 등을 JSON 에 저장해야 할 때  비즈니스 모델상태 모델으로 변환하고상태 모델을 직렬화 할 수 있습니다. JSON 를 직렬화 해제해야 할 때  상태 모델으로 직렬화 해제 한 후비즈니스 모델으로 변환해야합니다. JavaFX  필요한 경우 사용자 정의 직렬 변환기 및 디시리얼라이저를 구현해야하는 클래스 그들은 또한 정기적 인 POJO 가 아닙니다  수업에 특별한 대우가 필요합니다.

    2 개의 시리얼 라이저와 1 개의 디시리얼라이저를 구현하자 :

    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  방법은 부작용이 있습니다. 그것은 삶을 제거합니다-그것이 무엇을 의미하든. 일반적으로 나쁜 습관이지만이 질문은 이름 지정에 관한 것이 아닙니다.

  • 이전 logging - 델파이 - 어설 션을 사용하지 않고 얻는 방법 (현재 코드 라인, 현재 단위, 현재 기능)?
  • 다음 python - 목록 값을 정확히 같지 않은 데이터 프레임 열과 비교하려면 어떻게합니까?