我有一个类似于此类的帖子:
@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-reactive-driver使用该类存储在Mongo数据库中。 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
(没有创造者, 像默认构造一样,存在):无法从Object值反序列化 (没有基于委托人或财产的创建者)
我想要的是在测试中使用“纬度”和“经度” json字段序列化对象,同时保持其余实现逻辑按原样工作。这该怎么做?
答案 0 :(得分:0)
哦,很好。只需通过更改api来接受自定义“位置”字段并编写杰克逊序列化器即可解决此问题:
@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();
}
}
}