Gson: Serializing a class with two Date fields - java

I am trying to serialize a class that has two Date fields defined:
import com.google.gson.annotations.Expose;
import java.util.Date;
public class DateRange {
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
#Expose
public Date startDate;
#Expose
public Date endDate;
public DateRange(Date startDate, Date endDate) {
this.startDate = startDate;
this.endDate = endDate;
}
public DateRange(String startDate, String endDate ) throws ParseException{
this.startDate = dateFormat.parse(startDate);
this.endDate = dateFormat.parse(endDate);
}
}
but using gson.toJson an exception is thrown where multiple
import com.google.gson.Gson
Gson gson = new Gson()
gson.toJson(new DateRange("2011-11-11", "2012-11-11"))
results in
java.lang.IllegalArgumentException: class java.text.DecimalFormat declares multiple JSON fields named maximumIntegerDigits
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:166)
The problem is exacerbated where I have a class ManyDates which has a field with DateRange as well as another field with an array of DateRange. I have attempted adding the field as a private transient but no luck (also tried with the field as a String type)
private transient java.text.DecimalFormat maximumIntegerDigits;
but the field is still causing issues with the serialization. I'm not sure where that field is even coming from but I suspect a simple solution to this must be just out of reach that I'm just not seeing.

In this case gson tries to serialize dateFormat field.
just annotate it with #Transient

Related

How do I use different date formats for serialization & deserialization?

I'm getting an object with the date field in the format 2022-02-11 which I'm mapping into an object as follows:
{ "dateTimeField": "2022-02-11" }
#Data
class MyPojo {
#JsonFormat(pattern = "yyyy-MM-dd")
private Date dateTimeField;
}
Now I need to send this object as a json response, but I need it to be in a different format:
{ "dateTimeField": "2022-02-11 00:00:00" }
If I change the pattern field, deserialization fails:
#Data
class MyPojo {
// com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date` from String "2022-02-11": expected format "yyyy-MM-dd HH:mm:ss"
#JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date dateTimeField;
}
How do I use different patterns for serialization & deserialization?
This can be accomplished using separate annotations on the getter and setter of the field:
#Data
class MyPojo {
private Date dateTimeField;
// Used during serialization
#JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public Date getDateTimeField() {
return dateTimeField;
}
// Used during deserialization
#JsonFormat(pattern = "yyyy-MM-dd")
public void setDateTimeField(Date dateTimeField) {
this.dateTimeField = dateTimeField;
}
}
Alternatively, using Lombok's (experimental as of 11 Feb 2022) onX feature:
#Data
class MyPojo {
#Getter(onMethod_ = {#JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")}) // Used during serialization
#Setter(onMethod_ = {#JsonFormat(pattern = "yyyy-MM-dd")}) // Used during deserialization
private Date dateTimeField;
}

Problem with formatting LocalDateTime with org.json library

I have a problem with the serialization of an object to JSON using the org.json library.
In my code I have:
String resultStr = new JSONObject(result).toString();
and in result object two fields of type LocalDateTime:
private LocalDateTime startDate;
private LocalDateTime stopDate;
In variable resultStr I got date in following format:
2020-01-23T14:13:30.121205
I want this ISO format:
2016-07-14T07:58:08.158Z
I know that in Jackson there is an annotation #JsonFormat, but I didn't find anything like that in org.json. How to define a format of LocalDateTime in JSON string with org.json?
In JSON in Java, it seems that there are not much support for Date/Time formatting.
To customize the formatting of LocalDateTime field, we can make use of
1. #JSONPropertyIgnore to ignore the original getter to be serialized
2. #JSONPropertyName to annotate a new getter with ignored field name, which return the desired formatted date string, as following:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.json.JSONObject;
import org.json.JSONPropertyIgnore;
import org.json.JSONPropertyName;
public class CustomizeLocalDateTimeFormatInOrgJson {
public static void main(String[] args) {
Result result = new Result(LocalDateTime.now(), LocalDateTime.now());
String resultStr = new JSONObject(result).toString();
System.out.println(resultStr);
}
public static class Result {
DateTimeFormatter customDateTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssS'Z'");
private LocalDateTime startDate;
#JSONPropertyIgnore
public LocalDateTime getStartDate() {
return startDate;
}
#JSONPropertyName("startDate")
public String getStartDateString() {
return customDateTimeFormat.format(startDate);
}
private LocalDateTime stopDate;
#JSONPropertyIgnore
public LocalDateTime getStopDate() {
return stopDate;
}
#JSONPropertyName("stopDate")
public String getStopDateString() {
return customDateTimeFormat.format(stopDate);
}
public void setStopDate(LocalDateTime stopDate) {
this.stopDate = stopDate;
}
public void setStartDate(LocalDateTime startDate) {
this.startDate = startDate;
}
public Result(LocalDateTime startDate, LocalDateTime stopDate) {
super();
this.startDate = startDate;
this.stopDate = stopDate;
}
}
}

Jackson Adding a Custom Serializer for all fields of Type X

I have a class like this:
public class Foo {
private Integer id;
private FooB fooA;
private boolean isB;
private boolean isC;
private int age;
private LocalDate date1;
private LocalDate date2;
private LocalDate date3;
private LocalDate date4;
}
I want to serialize everything in this class natively except for the LocalDate fields. I have a custom serializer for that like so:
public class LocalDateSerializer extends JsonSerializer<LocalDate> {
#Override
public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
//serialize
}
}
Is there a way to annotate the class Foo to say only use the serializer for objects of type LocalDate or do I have to go annotate each individual field like so:
public class Foo {
private Integer id;
private FooB fooA;
private boolean isB;
private boolean isC;
private int age;
#JsonSerialize(using = LocalDateSerializer.class)
private LocalDate date1;
#JsonSerialize(using = LocalDateSerializer.class)
private LocalDate date2;
#JsonSerialize(using = LocalDateSerializer.class)
private LocalDate date3;
#JsonSerialize(using = LocalDateSerializer.class)
private LocalDate date4;
}
My question is, can I consolidate that into a single class level annotation?
I couldn't find a solution that uses only one annotation in the class. Probably annotating each field is the best you can get.
Another way is to configure the ObjectMapper programatically:
ObjectMapper om = new ObjectMapper();
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("dd/MM/yyyy")));
om.registerModule(module);
The addSerializer method maps all LocalDate fields to use the specified serializer. In the example above, I used the built-in com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer with a DateTimeFormatter, but of course you can replace it with any serializer you want (including your custom one).
If you don't want to (or can't) configure the ObjectMapper, then using the annotations on each field seems to be the best solution.

Converting date from timestamp to human readable in entity constructor

Currently, the format of the Date requestDate variable stored looks like: 2017-02-17 00:00:00.0. I want to convert this into, for example: Friday, February 17, 2017. I would like to do the conversion here in my entity and return it so that when it's displayed it is more human readable. This will likely happen in the constructor, at this line: this.setRequestDate(doDateConversion(requestDate));. How can I make this conversion?
My Request entity:
#Entity
#Table(name = "Request")
public class RequestDO implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="request_id")
private Long id;
private Date requestDate;
private String description;
private RequestStatus status;
/*private Boolean read;*/
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="user_id", nullable = false)
private Users users;
public RequestDO() {}
public RequestDO(Users user, Date requestDate) {
this.setUsers(user);
this.setRequestDate(requestDate);
}
#Override
public String toString() {
return String.format(
"RequestDO[id=%d, inital='%s', requestDate='%s']",
getId()
, getUsers().getInitialName()
, getRequestDate());
}
public Date getRequestDate() {
return requestDate;
}
public void setRequestDate(Date requestDate) {
this.requestDate = requestDate;
}
}
You can use SimpleDateFormat to convert your Date to a readable String of your choice.
The time format String for your example is EEEE, MMMM, dd, yyyy. You have to create a new SimpleDateFormat object and format your date to a String. Examples...
But Spring provides some specials out of the box. For example you can use Jackson for date format: #JsonFormat(pattern="yyyy-MM-dd") more. It is also possible to add a data format in application.properties file : spring.jackson.date-format
Using SimpleDateFormat:
java.sql.Date date = new Date(System.currentTimeMillis());
System.out.println(new SimpleDateFormat("EEEE, MMMM dd, YYYY").format(date));
See this for more details.
I solved the problem by changing the dates as they are read in my controller, using SimpleDateFormat:
#RequestMapping(value = "/requests", method = RequestMethod.GET)
public String getAllRequests(Model model, RequestModel requestModel) throws ParseException {
List<RequestDO> requestDOArrayList = new ArrayList<RequestDO>();
for (RequestDO requestDO : requestRepository.findAll()) {
log.info(requestDO.toString());
// Display all dates in Requests list in human-readable form
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(requestDO.getRequestDate().toString());
log.info(String.valueOf(date));
requestDO.setRequestDate(date);
requestDOArrayList.add(requestDO);
}
model.addAttribute("requests", requestDOArrayList);
log.info(requestDOArrayList.toString());
return "requests";
}

java.sql.Date not inserted into datatables

I have a class wich contains:
#Column(name = "end_date")
private Date endDate;
and it's setter
public void setEndDate() {
endDate = new java.sql.Date(Calendar.getInstance().getTime().getTime());
System.out.println(endDate);
}
When I'm calling the setter, and check again if the value is correct, everything's fine.(even getEndDate().getClass() ).
However, when I'm saving my object into PostgreSQL (myObject.persist()), there's no value on END_TIME column. Other values are correct.
Does anyone know what's the problem?
Also, I have to mention that hibernate is set to create SQL tables
Setter and getter:
public void setEndDate(Date endDate) {
setEndDate();
}
public Date getEndDate() {
return endDate;
}
import java.util.Date instead of import java.sql.date
assign current date as per following code
default date assign while creating object of this entity if user need to change then using setter on run time
try this it will work
#Column(name = "END_TIME")
private Date endDate = new Date();
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public Date getEndDate() {
return endDate;
}
I use java.util.Date for this case, and change the mapping of your #Column as
#Column(name = "end_time")
private Date endDate = new Date();
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public Date getEndDate() {
return endDate;
}

Categories

Resources