ZoneDateTime在PostgreSQL中存储为JSONB的序列化格式
Serialisation format of ZoneDateTime stored as JSONB in PostgreSQL
尝试在 PostgreSQL 中将复杂数据存储为 JSONB。
除了 java.time.ZonedDateTime.
类型的属性格式外,存储工作正常
1 - 给出的是实体 Route:
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
…
class
…
@Column(name = "stops", columnDefinition = "jsonb")
@Type(type = "jsonb")
@Valid
private List<Stop> stops;
…
它有一个 @Embeddable 对象 Stop 包含属性:
@Column(name = "date_from")
private ZonedDateTime dateFrom;
2 - 当 POST REST 端点接收到:
{…
"dateFrom": "2018-07-28T17:47:50.331+02:00",
…}
整个 JSON 到实体的映射有效!
但是
3 - 然后 postgreSQL 数据库存储为日期:
{…
"loadingDateFrom": {
"hour": 17,
"nano": 331000000,
"year": 2018,
"zone": {
"id": "+02:00",
"rules": {
"fixedOffset": true,
"transitions": [],
"transitionRules": []
},
"totalSeconds": 7200
},
"month": "JULY",
"minute": 47,
"offset": {
"id": "+02:00",
"rules": {
"fixedOffset": true,
"transitions": [],
"transitionRules": []
},
"totalSeconds": 7200
},
"second": 50,
"dayOfWeek": "SATURDAY",
"dayOfYear": 209,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
},
"dayOfMonth": 28,
"monthValue": 7
},
…}
预期与端点接收的相同(日期字符串):
"2018-07-28T17:47:50.331+02:00"
(其他示例:如果存储为 postgreSQL 时间戳,就像实体 Stop 中的不同属性一样,序列化为日期字符串工作正常)
调用 GET REST 端点会传递复杂的日期结构,这很糟糕,因为前端的日期处理很复杂。
问题:
如何实现postgreSQL将日期存储为日期字符串,而不是一个复杂的对象?
经过大量调试后,我认为它与 Jackson 串行器有关。我看到 DefaultSerializer 正在获取一个 ZonedDateTime 对象。序列化后存储复杂的数据结构。
有没有一种配置方式来格式化日期而不是自己写 serialiser/deserialiser?
我试过:
- 在日期属性上不同 @JsonFormat(…) 但总是 "JSON parse error" 用于反序列化。无论如何,我不想指定格式。这应该是开箱即用的。
配置:
jhipster/spring-boot 项目
-编译"com.fasterxml.jackson.datatype:jackson-datatype-jsr310"
-编译"com.fasterxml.jackson.core:jackson-databind"
- spring: 杰克逊: serialization.write_dates_as_timestamps: 假
使用 CustomSerializer:
public class ZonedDateTimeSerialzier extends JsonSerializer<ZonedDateTime>{
@Override
public void serialize(ZonedDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
String parseDate = null;// parse here zoned date time
gen.writeString(parseDate);
}
}
然后添加:
@Column(name = "date_from")
@JsonSerialize(using = ZonedDateTimeSerialzier.class)
private ZonedDateTime dateFrom;
如果你想全局执行,那么在配置中写入这个 bean class:
@Bean
public Jackson2ObjectMapperBuilder configureObjectMapper() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
SimpleModule zonedDateTimeSerializer = new SimpleModule();
zonedDateTimeSerializer.addSerializer(ZonedDateTime.class,new ZonedDateTimeSerialzier());
builder.modules(zonedDateTimeSerializer);
return builder;
}
或者,如果您想要时间戳,请将其添加到 application.properties:
spring.jackson.serialization.write-dates-as-timestamps=true
或application.yml:
spring:
jackson:
serialization:
write-dates-as-timestamps: true
信息:
我将@sajib 标记为正确答案,因为没有其他解决方案出现。
我用过:
@JsonSerialize(using = ZonedDateTimeSerializier.class)
@JsonDeserialize(using = ZonedDateTimeDeserializier.class)
将 Date 序列化为 String 并将 String 反序列化为 Date
尝试在 PostgreSQL 中将复杂数据存储为 JSONB。
除了 java.time.ZonedDateTime.
1 - 给出的是实体 Route:
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
…
class
…
@Column(name = "stops", columnDefinition = "jsonb")
@Type(type = "jsonb")
@Valid
private List<Stop> stops;
…
它有一个 @Embeddable 对象 Stop 包含属性:
@Column(name = "date_from")
private ZonedDateTime dateFrom;
2 - 当 POST REST 端点接收到:
{…
"dateFrom": "2018-07-28T17:47:50.331+02:00",
…}
整个 JSON 到实体的映射有效!
但是
3 - 然后 postgreSQL 数据库存储为日期:
{…
"loadingDateFrom": {
"hour": 17,
"nano": 331000000,
"year": 2018,
"zone": {
"id": "+02:00",
"rules": {
"fixedOffset": true,
"transitions": [],
"transitionRules": []
},
"totalSeconds": 7200
},
"month": "JULY",
"minute": 47,
"offset": {
"id": "+02:00",
"rules": {
"fixedOffset": true,
"transitions": [],
"transitionRules": []
},
"totalSeconds": 7200
},
"second": 50,
"dayOfWeek": "SATURDAY",
"dayOfYear": 209,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
},
"dayOfMonth": 28,
"monthValue": 7
},
…}
预期与端点接收的相同(日期字符串):
"2018-07-28T17:47:50.331+02:00"
(其他示例:如果存储为 postgreSQL 时间戳,就像实体 Stop 中的不同属性一样,序列化为日期字符串工作正常)
调用 GET REST 端点会传递复杂的日期结构,这很糟糕,因为前端的日期处理很复杂。
问题:
如何实现postgreSQL将日期存储为日期字符串,而不是一个复杂的对象?
经过大量调试后,我认为它与 Jackson 串行器有关。我看到 DefaultSerializer 正在获取一个 ZonedDateTime 对象。序列化后存储复杂的数据结构。
有没有一种配置方式来格式化日期而不是自己写 serialiser/deserialiser?
我试过:
- 在日期属性上不同 @JsonFormat(…) 但总是 "JSON parse error" 用于反序列化。无论如何,我不想指定格式。这应该是开箱即用的。
配置:
jhipster/spring-boot 项目
-编译"com.fasterxml.jackson.datatype:jackson-datatype-jsr310"
-编译"com.fasterxml.jackson.core:jackson-databind"
- spring: 杰克逊: serialization.write_dates_as_timestamps: 假
使用 CustomSerializer:
public class ZonedDateTimeSerialzier extends JsonSerializer<ZonedDateTime>{
@Override
public void serialize(ZonedDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
String parseDate = null;// parse here zoned date time
gen.writeString(parseDate);
}
}
然后添加:
@Column(name = "date_from")
@JsonSerialize(using = ZonedDateTimeSerialzier.class)
private ZonedDateTime dateFrom;
如果你想全局执行,那么在配置中写入这个 bean class:
@Bean
public Jackson2ObjectMapperBuilder configureObjectMapper() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
SimpleModule zonedDateTimeSerializer = new SimpleModule();
zonedDateTimeSerializer.addSerializer(ZonedDateTime.class,new ZonedDateTimeSerialzier());
builder.modules(zonedDateTimeSerializer);
return builder;
}
或者,如果您想要时间戳,请将其添加到 application.properties:
spring.jackson.serialization.write-dates-as-timestamps=true
或application.yml:
spring:
jackson:
serialization:
write-dates-as-timestamps: true
信息:
我将@sajib 标记为正确答案,因为没有其他解决方案出现。
我用过:
@JsonSerialize(using = ZonedDateTimeSerializier.class)
@JsonDeserialize(using = ZonedDateTimeDeserializier.class)
将 Date 序列化为 String 并将 String 反序列化为 Date