Skip to content

Commit

Permalink
Add support for using OffsetDateTime in JSON objects #408
Browse files Browse the repository at this point in the history
  • Loading branch information
arolfes authored and vladmihalcea committed Mar 23, 2022
1 parent 1f84c01 commit ed7f746
Show file tree
Hide file tree
Showing 4 changed files with 348 additions and 6 deletions.
@@ -1,12 +1,17 @@
package com.vladmihalcea.hibernate.type.util;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.hibernate.HibernateException;

import java.io.IOException;
import java.lang.reflect.Type;
import java.time.OffsetDateTime;

import static java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME;

/**
* Wraps a Jackson {@link ObjectMapper} so that you can supply your own {@link ObjectMapper} reference.
Expand All @@ -23,7 +28,14 @@ public class ObjectMapperWrapper {
private JsonSerializer jsonSerializer;

public ObjectMapperWrapper() {
this(new ObjectMapper().findAndRegisterModules());
this(new ObjectMapper()
.findAndRegisterModules()
.registerModule(
new SimpleModule()
.addSerializer(OffsetDateTime.class, OffsetDateTimeSerializer.INSTANCE)
.addDeserializer(OffsetDateTime.class, OffsetDateTimeDeserializer.INSTANCE)
)
);
}

public ObjectMapperWrapper(ObjectMapper objectMapper) {
Expand Down Expand Up @@ -112,4 +124,41 @@ public JsonNode toJsonNode(String value) {
public <T> T clone(T value) {
return jsonSerializer.clone(value);
}

public static class OffsetDateTimeSerializer extends com.fasterxml.jackson.databind.JsonSerializer<OffsetDateTime> {

public static final OffsetDateTimeSerializer INSTANCE = new OffsetDateTimeSerializer();

@Override
public void serialize(OffsetDateTime offsetDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (offsetDateTime == null) {
jsonGenerator.writeNull();
} else {
jsonGenerator.writeString(offsetDateTime.format(ISO_OFFSET_DATE_TIME));
}
}

@Override
public Class<OffsetDateTime> handledType() {
return OffsetDateTime.class;
}
}

public static class OffsetDateTimeDeserializer extends JsonDeserializer<OffsetDateTime> {

public static final OffsetDateTimeDeserializer INSTANCE = new OffsetDateTimeDeserializer();

@Override
public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
if (jsonParser.getText() != null) {
return OffsetDateTime.parse(jsonParser.getText(), ISO_OFFSET_DATE_TIME);
}
return null;
}

@Override
public Class<OffsetDateTime> handledType() {
return OffsetDateTime.class;
}
}
}
@@ -0,0 +1,122 @@
package com.vladmihalcea.hibernate.type.json;

import com.vladmihalcea.hibernate.util.AbstractPostgreSQLIntegrationTest;
import org.hibernate.annotations.TypeDef;
import org.junit.Test;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;

import static org.junit.Assert.assertEquals;

/**
* @author Vlad Mihalcea
*/
public class OffsetDateTimeJsonTest extends AbstractPostgreSQLIntegrationTest {

@Override
protected Class<?>[] entities() {
return new Class<?>[]{
Event.class,
};
}

@Test
public void test() {
OffsetDateTime dateTime = OffsetDateTime.of(2015, 10, 1, 9, 0 , 0, 0, ZoneOffset.ofHours(2));

doInJPA(entityManager -> {
Location location = new Location();
location.setCountry("Romania");
location.setCity("Cluj-Napoca");
location.setRentedAt(dateTime);

Event event = new Event();
event.setId(1L);
event.setLocation(location);
entityManager.persist(event);
});

doInJPA(entityManager -> {
Event event = entityManager.find(Event.class, 1L);
assertEquals(dateTime, event.getLocation().getRentedAt());
});
}

@Entity(name = "Event")
@Table(name = "event")
@TypeDef(defaultForType = Location.class, typeClass = JsonType.class)
public static class Event {

@Id
private Long id;

@Column(columnDefinition = "jsonb")
private Location location;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public Location getLocation() {
return location;
}

public void setLocation(Location location) {
this.location = location;
}
}

public static class Location implements Serializable {

private String country;

private String city;

private BigDecimal reference;

private OffsetDateTime rentedAt;

public String getCountry() {
return country;
}

public void setCountry(String country) {
this.country = country;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public BigDecimal getReference() {
return reference;
}

public void setReference(BigDecimal reference) {
this.reference = reference;
}

public OffsetDateTime getRentedAt() {
return rentedAt;
}

public void setRentedAt(OffsetDateTime rentedAt) {
this.rentedAt = rentedAt;
}
}
}
@@ -1,12 +1,17 @@
package com.vladmihalcea.hibernate.type.util;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.hibernate.HibernateException;

import java.io.IOException;
import java.lang.reflect.Type;
import java.time.OffsetDateTime;

import static java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME;

/**
* Wraps a Jackson {@link ObjectMapper} so that you can supply your own {@link ObjectMapper} reference.
Expand All @@ -23,7 +28,14 @@ public class ObjectMapperWrapper {
private JsonSerializer jsonSerializer;

public ObjectMapperWrapper() {
this(new ObjectMapper().findAndRegisterModules());
this(new ObjectMapper()
.findAndRegisterModules()
.registerModule(
new SimpleModule()
.addSerializer(OffsetDateTime.class, OffsetDateTimeSerializer.INSTANCE)
.addDeserializer(OffsetDateTime.class, OffsetDateTimeDeserializer.INSTANCE)
)
);
}

public ObjectMapperWrapper(ObjectMapper objectMapper) {
Expand Down Expand Up @@ -112,4 +124,41 @@ public JsonNode toJsonNode(String value) {
public <T> T clone(T value) {
return jsonSerializer.clone(value);
}

public static class OffsetDateTimeSerializer extends com.fasterxml.jackson.databind.JsonSerializer<OffsetDateTime> {

public static final OffsetDateTimeSerializer INSTANCE = new OffsetDateTimeSerializer();

@Override
public void serialize(OffsetDateTime offsetDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (offsetDateTime == null) {
jsonGenerator.writeNull();
} else {
jsonGenerator.writeString(offsetDateTime.format(ISO_OFFSET_DATE_TIME));
}
}

@Override
public Class<OffsetDateTime> handledType() {
return OffsetDateTime.class;
}
}

public static class OffsetDateTimeDeserializer extends JsonDeserializer<OffsetDateTime> {

public static final OffsetDateTimeDeserializer INSTANCE = new OffsetDateTimeDeserializer();

@Override
public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
if (jsonParser.getText() != null) {
return OffsetDateTime.parse(jsonParser.getText(), ISO_OFFSET_DATE_TIME);
}
return null;
}

@Override
public Class<OffsetDateTime> handledType() {
return OffsetDateTime.class;
}
}
}

0 comments on commit ed7f746

Please sign in to comment.