Джексон сериализует GeoJsonPoint как широту / долготу - PullRequest
0 голосов
/ 21 октября 2018

У меня есть класс Post, который выглядит следующим образом:

@Document(collection = "Posts")
@Data
public class Post {

    @Id
    private ObjectId _id;
    @NonNull private String userId;
    @NonNull private String firstName;
    @NonNull private String lastName;
    private String postText;
    private String postImageUri;
    @NonNull private String googlePlaceId;
    @NonNull private String googlePlaceName;
    @NonNull private GeoJsonPoint location;

    @JsonCreator
    public Post(@JsonProperty("userId") String userId,
                @JsonProperty("firstName")String firstName,
                @JsonProperty("lastName")String lastName,
                @JsonProperty("postText") String postText,
                @JsonProperty("postImageUri") String postImageUri,
                @JsonProperty("googlePlaceId") String googlePlaceId,
                @JsonProperty("googlePlaceName") String googlePlaceName,
                @JsonProperty("latitude") long latitude,
                @JsonProperty("longitude") long longitude) {
        this.userId = userId;
        this.firstName = firstName;
        this.lastName = lastName;
        this.postText = postText;
        this.postImageUri = postImageUri;
        this.googlePlaceId = googlePlaceId;
        this.googlePlaceName = googlePlaceName;
        this.location = new GeoJsonPoint(longitude, latitude);
    }

}

Этот класс используется Mongo-реактивным-драйвером для хранения в базе данных Mongo db.GeoJsonPoint - это специальный тип, который сохраняется, поэтому я не хочу хранить поля широты и долготы отдельно.

В основном мой код работает хорошо.Использование Spring boot:

@PostMapping("")
public Mono<ResponseEntity<Post>> savePost(@RequestBody final Post post) {
    // Fire and forgat
    ablyService.publishPost(post.getGooglePlaceId(), post);
    return postRepo.save(post)
            .map(savedPost -> new ResponseEntity<>(savedPost, HttpStatus.CREATED));
}

Моя проблема в том, что я пишу интеграционный тест.Что я хочу сделать:

@Test
public void createPostTest() {
    Post post = new Post("someUserId", "Kim", "Gysen",
            "Some text", "http://zwoop.be/imagenr",
            "googlePlaceId", "googlePlaceName", 50, 50);

    webTestClient.post().uri(BASE_URI)
            .contentType(MediaType.APPLICATION_JSON_UTF8)
            .accept(MediaType.APPLICATION_JSON_UTF8)
            .body(Mono.just(post), Post.class)
            .exchange()
            .expectStatus().isCreated()
            .expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
            .expectBody()
            .jsonPath("$._id").isNotEmpty()
            .jsonPath("$.userId").isEqualTo(post.getUserId())
            .jsonPath("$.firstName").isEqualTo(post.getFirstName())
            .jsonPath("$.lastName").isEqualTo(post.getLastName())
            .jsonPath("$.postText").isEqualTo(post.getPostText())
            .jsonPath("$.postImageUri").isEqualTo(post.getPostImageUri())
            .jsonPath("$.location.x").isEqualTo(post.getLocation().getX())
            .jsonPath("$.location.y").isEqualTo(post.getLocation().getY());
}

Я получаю ошибку:

org.springframework.core.codec.CodecException: Ошибка определения типа: [простой тип, класс org.springframework.data.mongodb.core.geo.GeoJsonPoint];вложенное исключение: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: невозможно создать экземпляр org.springframework.data.mongodb.core.geo.GeoJsonPoint (не существует создателей, таких как создание по умолчанию): невозможно десериализовать из значения объекта (без создателя на основе делегатов или свойств)

Мне нужно сериализовать объект с полями json "широта" и "долгота", сохраняя при этом остальную часть моей логики реализации, работающей как есть.Как это сделать?

1 Ответ

0 голосов
/ 21 октября 2018

Ну хорошо.Просто исправили это, изменив API для принятия пользовательского поля 'location' и написав сериализатор Джексона:

@Document(collection = "Posts")
@Data
public class Post {

    @Id
    private ObjectId _id;
    @NonNull private String userId;
    @NonNull private String firstName;
    @NonNull private String lastName;
    private String postText;
    private String postImageUri;
    @NonNull private String googlePlaceId;
    @NonNull private String googlePlaceName;
    @JsonSerialize(using = LocationToLatLngSerializer.class)
    @NonNull private GeoJsonPoint location;

    @JsonCreator
    public Post(@JsonProperty("userId") String userId,
                @JsonProperty("firstName")String firstName,
                @JsonProperty("lastName")String lastName,
                @JsonProperty("postText") String postText,
                @JsonProperty("postImageUri") String postImageUri,
                @JsonProperty("googlePlaceId") String googlePlaceId,
                @JsonProperty("googlePlaceName") String googlePlaceName,
                @JsonProperty("location") Geolocation location) {
        this.userId = userId;
        this.firstName = firstName;
        this.lastName = lastName;
        this.postText = postText;
        this.postImageUri = postImageUri;
        this.googlePlaceId = googlePlaceId;
        this.googlePlaceName = googlePlaceName;
        this.location = new GeoJsonPoint(location.getLongitude(), location.getLatitude());
    }

    static class LocationToLatLngSerializer extends JsonSerializer<GeoJsonPoint> {

        @Override
        public void serialize(GeoJsonPoint value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeStartObject();
            gen.writeNumberField("latitude", value.getX());
            gen.writeNumberField("longitude", value.getY());
            gen.writeEndObject();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...