使用 Spring 数据 REST 的 JsonMappingException:当 @Id 从正在映射的列表中删除时选择了错误的序列化程序
JsonMappingException using Spring Data REST: Selects wrong serializer when @Id is removed from the list that that is being mapped
我创建了一个 project on gitlab(url),我想在其中使用 Spring Data REST 来保存和公开一些传感器数据。使用 HAL 浏览器进行测试时,持久化到 PostgreSQL 数据库没有问题,但是 SensorReading GET 给我带来了一些麻烦:
Could not write JSON: java.lang.Integer cannot be cast to java.lang.Double; nested exception is com.fasterxml.jackson.databind.JsonMappingException: java.lang.Integer cannot be cast to java.lang.Double (through reference chain: org.springframework.hateoas.Resources[\"_embedded\"]>java.util.Collections$UnmodifiableMap[\"sensorReadings\"]>java.util.ArrayList[0]>org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$PersistentEntityResourceSerializer[\"content\"]->net.smurfz.kado.models.SensorReading[\"sensorId\"])
我@Entity-class中的代码(net.smurfz.kado.models.SensorReading):
@Entity
public class SensorReading {
@Id
@org.springframework.data.annotation.Id
@SequenceGenerator(name = "sensor_reading_id_seq",
sequenceName = "sensor_reading_id_seq",
allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "sensor_reading_id_seq")
@Column(updatable = false)
private Integer id;
@NotNull
private Integer sensorId;
@NotNull
private double reading;
@Column(name = "created_date")
@ReadOnlyProperty
private Date created;
public SensorReading() {
}
public SensorReading(Integer sensorId, double reading) {
this.sensorId = sensorId;
this.reading = reading;
}
public Integer getId() {
return id;
}
public Integer getSensorId() {
return sensorId;
}
public void setSensorId(Integer sensorId) {
this.sensorId = sensorId;
}
public double getReading() {
return reading;
}
public void setReading(double reading) {
this.reading = reading;
}
public Date getCreated() {
return created;
}
@PrePersist
protected void onCreate() {
created = new Date();
}
}
和我的@RepositoryRestResource-class (net.smurfz.kado.repositories.SensorReadingRepository):
@RepositoryRestResource
public interface SensorReadingRepository extends CrudRepository<SensorReading, Integer> {
List<SensorReading> findTop30BySensorIdOrderByCreatedDesc(Integer sensorId);
Long countAllBySensorId(Integer sensorId);
SensorReading findFirstBySensorIdOrderByCreatedDesc(Integer sensorId);
Page<SensorReading> findAllBySensorId(Integer sensorId, Pageable pageable);
}
现在,我尊敬的同事设法发现的快速修复方法是移动:
@Id
@org.springframework.data.annotation.Id
@SequenceGenerator(name = "sensor_reading_id_seq",
sequenceName = "sensor_reading_id_seq",
allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "sensor_reading_id_seq")
@Column(updatable = false)
private Integer id;
在所有其他字段声明下。
当 BeanSerializerFactory-class 尝试定义要使用的序列化程序时,此错误会在某处发生。我的工作理论是它最初识别 4 个字段(4 个列表),然后过滤掉不被序列化的 id(3 个列表),但决定在第二个列表中使用第一个列表中的索引 (1-3) ,导致 Integer 字段获得下面定义的双字段的序列化程序。
这是一个不需要的肮脏黑客,因为我真的不知道这可能会影响我想知道的其他事情:
a) 为什么会这样?
b) 应该做些什么来避免这个错误?
URL 上面的链接直接指向实施 id-fix 之前的提交。
引用@Damien 的评论:
I didnt no - based on this jira -
github.com/spring-projects/spring-boot/issues/9756. Changing the
version to 2.0.0.BUILD-SNAPSHOT resolves the issue. – Damien
springBootVersion = '2.0.0.BUILD-SNAPSHOT' 解决了这个问题。
我创建了一个 project on gitlab(url),我想在其中使用 Spring Data REST 来保存和公开一些传感器数据。使用 HAL 浏览器进行测试时,持久化到 PostgreSQL 数据库没有问题,但是 SensorReading GET 给我带来了一些麻烦:
Could not write JSON: java.lang.Integer cannot be cast to java.lang.Double; nested exception is com.fasterxml.jackson.databind.JsonMappingException: java.lang.Integer cannot be cast to java.lang.Double (through reference chain: org.springframework.hateoas.Resources[\"_embedded\"]>java.util.Collections$UnmodifiableMap[\"sensorReadings\"]>java.util.ArrayList[0]>org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$PersistentEntityResourceSerializer[\"content\"]->net.smurfz.kado.models.SensorReading[\"sensorId\"])
我@Entity-class中的代码(net.smurfz.kado.models.SensorReading):
@Entity
public class SensorReading {
@Id
@org.springframework.data.annotation.Id
@SequenceGenerator(name = "sensor_reading_id_seq",
sequenceName = "sensor_reading_id_seq",
allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "sensor_reading_id_seq")
@Column(updatable = false)
private Integer id;
@NotNull
private Integer sensorId;
@NotNull
private double reading;
@Column(name = "created_date")
@ReadOnlyProperty
private Date created;
public SensorReading() {
}
public SensorReading(Integer sensorId, double reading) {
this.sensorId = sensorId;
this.reading = reading;
}
public Integer getId() {
return id;
}
public Integer getSensorId() {
return sensorId;
}
public void setSensorId(Integer sensorId) {
this.sensorId = sensorId;
}
public double getReading() {
return reading;
}
public void setReading(double reading) {
this.reading = reading;
}
public Date getCreated() {
return created;
}
@PrePersist
protected void onCreate() {
created = new Date();
}
}
和我的@RepositoryRestResource-class (net.smurfz.kado.repositories.SensorReadingRepository):
@RepositoryRestResource
public interface SensorReadingRepository extends CrudRepository<SensorReading, Integer> {
List<SensorReading> findTop30BySensorIdOrderByCreatedDesc(Integer sensorId);
Long countAllBySensorId(Integer sensorId);
SensorReading findFirstBySensorIdOrderByCreatedDesc(Integer sensorId);
Page<SensorReading> findAllBySensorId(Integer sensorId, Pageable pageable);
}
现在,我尊敬的同事设法发现的快速修复方法是移动:
@Id
@org.springframework.data.annotation.Id
@SequenceGenerator(name = "sensor_reading_id_seq",
sequenceName = "sensor_reading_id_seq",
allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "sensor_reading_id_seq")
@Column(updatable = false)
private Integer id;
在所有其他字段声明下。
当 BeanSerializerFactory-class 尝试定义要使用的序列化程序时,此错误会在某处发生。我的工作理论是它最初识别 4 个字段(4 个列表),然后过滤掉不被序列化的 id(3 个列表),但决定在第二个列表中使用第一个列表中的索引 (1-3) ,导致 Integer 字段获得下面定义的双字段的序列化程序。
这是一个不需要的肮脏黑客,因为我真的不知道这可能会影响我想知道的其他事情:
a) 为什么会这样?
b) 应该做些什么来避免这个错误?
URL 上面的链接直接指向实施 id-fix 之前的提交。
引用@Damien 的评论:
I didnt no - based on this jira - github.com/spring-projects/spring-boot/issues/9756. Changing the version to 2.0.0.BUILD-SNAPSHOT resolves the issue. – Damien
springBootVersion = '2.0.0.BUILD-SNAPSHOT' 解决了这个问题。