I am trying to create json object from LocaLDateTime but for some reason it is creating json like so, look for issueAt and expireAt key
json {"userID":0,"deviceID":0,"refreshToken":"93180548-23b3-4d1b-8b5b-a105b7cff7f9","issuedAt":{"year":2021,"monthValue":10,"dayOfMonth":27,"hour":9,"minute":22,"second":31,"nano":0,"month":"OCTOBER","dayOfWeek":"WEDNESDAY","dayOfYear":300,"chronology":{"id":"ISO","calendarType":"iso8601"}},"expiresAt":{"year":2021,"monthValue":10,"dayOfMonth":28,"hour":9,"minute":22,"second":31,"nano":0,"month":"OCTOBER","dayOfWeek":"THURSDAY","dayOfYear":301,"chronology":{"id":"ISO","calendarType":"iso8601"}}}
I want it to be like so
batch: [0,0,29a1bf70-648e-4cb5-aef8-5377cf702875,2021-10-26T12:36:10,2021-10-27T12:36:10] .
My code for creating the 2 dates is below
String randomString = UUID.randomUUID().toString();
Instant myInstant1 = Instant.now().truncatedTo(ChronoUnit.SECONDS);
LocalDateTime issuedAt = LocalDateTime.ofInstant(myInstant1, ZoneId.systemDefault());
System.out.println("issued_at : " + issuedAt);
LocalDateTime expiresAt = issuedAt.plusDays(1);
System.out.println("expires_at: " + expiresAt.plusDays(1));
In the below code is where I get the error when I try to use mapto to add the json object to my class object.
JsonObject json = new JsonObject()
.put("userID", userID)
.put("deviceID", deviceID)
.put("refreshToken", randomString)
.put("issuedAt", issuedAt)
.put("expiresAt", expiresAt);
LOG.info("json {}", json.encode());
RefreshToken refreshTokenObj = json.mapTo(RefreshToken.class); //here I am trying to mapTo my class and I get the error
LOG.info("refreshTokenObj {}", refreshTokenObj);
The error I get is
2021-10-27 09:22:31.133+0330 [vert.x-eventloop-thread-1] ERROR com.galiy.main.MainVerticle - Unhandled:
java.lang.IllegalArgumentException: Cannot construct instance of java.time.LocalDateTime (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.galiy.security.refreshToken.RefreshToken["issuedAt"])
at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4236) ~[jackson-databind-2.11.4.jar:2.11.4]
and my RefreshToken model is like so,
public class RefreshToken {
private Integer id;
private Integer userID;
private Integer deviceID;
private String refreshToken;
private LocalDateTime issuedAt;
private LocalDateTime expiresAt;
I am not familiar with Vert.x. But according to our discussion under the post, I simply add following 2 line of code before mapTo() and got no error.
ObjectMapper objectMapper = DatabindCodec.mapper();
objectMapper.registerModule(new JavaTimeModule());
Console output:
RefreshToken{id=null, userID=0, deviceID=0, refreshToken='9da220ce-bc66-4561-b924-988c7f394f2d', issuedAt=2021-10-27T17:21:28, expiresAt=2021-10-28T17:21:28}
And in my experience, you can also configure ObjectMapper to handle the output format of LocalDateTime as you want while serialization as follows:
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
You will need to annotate your LocalDateTime member as follows:
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss")
LocalDateTime myTime
Here is the link to full answer that explains all the details: Spring Data JPA - ZonedDateTime format for json serialization
Related
I'm having a OffsetDateTime field in my POJO:
#NotBlank(message = "startTime cannot be null or empty; ")
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
#JsonSerialize(using = OffsetDateTimeSerializer.class)
private OffsetDateTime startTime;
When I try to give the request body for the API with this offsetTime JSON field, it shows deserialization error:
: Resolved
[org.springframework.http.converter.HttpMessageNotReadableException:
JSON parse error: Cannot deserialize value of type `java.time.OffsetDateTime`
from String "2020-07-21T12:12:23.000+0200":
Failed to deserialize java.time.OffsetDateTime: (java.time.format.DateTimeParseException)
Text '2020-07-21T12:12:23.000+0200' could not be parsed at index 23;
nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException:
Cannot deserialize value of type `java.time.OffsetDateTime`
from String "2020-07-21T12:12:23.000+0200":
Failed to deserialize java.time.OffsetDateTime: (java.time.format.DateTimeParseException)
Text '2020-07-21T12:12:23.000+0200' could not be parsed at index 23
Is my input correct and how to deserialize this field from JSON?
I am trying to extract a value of predefined type (Boolean, Integer, joda.DateTime) from an arbitrary json that is sent as a String.
Eg: {"node1":{"node2":"2019-01-01T05:00:00.000Z"}}} and say I know that the value in this Json is a DateTime and I can extract the value 2019-01-01T05:00:00.000Z from this Json and disabled SerializationFeature.WRITE_DATES_AS_TIMESTAMPS.
When I try to serialize a simple String representation "1972-12-28T12:00:01.000Z" of org.joda.time.DateTime, it fails with JsonParseException: Unexpected character. However serialization will succeed for Booleans or DateTime string inside a TextNode.
I have have registered com.fasterxml.jackson.datatype.joda.JodaModule with my object mapper.
I have tried a few things, see the Junit test below
public class Tester {
public static class Bean {
public void Bean(){}
public DateTime start;
}
#Test
public void testJodaJsonSerialization() throws Exception{
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.registerModule(new JodaModule());
final String INPUT_JSON = "{\"start\" : \"1972-12-28T12:00:01.000Z\"}";
Bean bean = objectMapper.readValue(INPUT_JSON, Bean.class);
assertNotNull(bean.start);
System.out.println(objectMapper.writeValueAsString(bean)); //serializing as part of an object works
String boolAsString = "true";
Boolean aBoolean = objectMapper.readValue(boolAsString, Boolean.class); //works for bool (simple type)
System.out.println(aBoolean);
String dateAsTextNode = objectMapper.writeValueAsString(new TextNode("1972-12-28T12:00:01.000Z")); //works for TextNode
System.out.println("dateAsTextNode: " + dateAsTextNode);
DateTime dateTime = objectMapper.readValue(dateAsTextNode, DateTime.class);
System.out.println(dateTime);
JsonNode jsonRoot = objectMapper.readTree(INPUT_JSON);
String datetimeAsString = jsonRoot.get("start").asText();
objectMapper.readValue(objectMapper.writeValueAsString(new TextNode(datetimeAsString)), DateTime.class); //this workaround will work
objectMapper.readValue(objectMapper.writeValueAsString(new TextNode(boolAsString)), Boolean.class);
String dateAsString = "1972-12-28T12:00:01.000Z";
objectMapper.readValue(dateAsString, DateTime.class); //but this fails
}
}
I expect String serialization to work just like it does on the TextNode
Your String
String dateAsString = "1972-12-28T12:00:01.000Z";
contains the content
1972-12-28T12:00:01.000Z
which is not valid JSON, so Jackson cannot parse it.
It would be valid JSON if it contained leading quotes, so
String dateAsString = "\"1972-12-28T12:00:01.000Z\"";
and then parsing would succeed.
You can configure the pattern of the date format on the ObjectMapper level:
Value dateFormat = Value.forShape(Shape.STRING)
.withPattern("MM/dd/yyyy HH:mm:ss")
.withTimeZone(TimeZone.getTimeZone("UTC"));
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule())
.configOverride(DateTime.class).setFormat(dateFormat);
I am converting a JSON file into Java object using Jackson with Java 8 Module. But while converting JSON array to LocalDate[] application is throwing an exception.
How to convert below JSON array to LocalDate[] using annotations?
JSON
{
"skip": [
"01/01/2019",
"26/01/2019"
]
}
Code
#JsonFormat(pattern = "dd/MM/yyyy")
#JsonSerialize(using = LocalDateSerializer.class)
#JsonDeserialize(using = LocalDateDeserializer.class)
private LocalDate[] skip;
Exception
com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (VALUE_STRING) within Array, expected VALUE_NUMBER_INT
at [Source: (ByteArrayInputStream); line: 25, column: 3] (through reference chain: com.saalamsaifi.springwfrlroster.model.Team["skip"])
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343)
at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer.deserialize(LocalDateDeserializer.java:110)
at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer.deserialize(LocalDateDeserializer.java:38)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3070)
Since skip is of type array, LocalDateSerializer, LocalDateDeserializer and JsonFormat do not work out of the box - they are implemented to expect direct value tokens and not arrays.
You can implement your own serializer/deserializers. A naive deserializer I implemented to deserialize your example is the following:
public class CustomLocalDateArrayDeserializer extends JsonDeserializer<LocalDate[]> {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
#Override
public LocalDate[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
ArrayList<LocalDate> list = new ArrayList<>();
JsonToken currentToken = p.getCurrentToken();
if (currentToken != JsonToken.START_ARRAY) {
throw new JsonMappingException(p, "Not an array!");
}
currentToken = p.nextToken();
while (currentToken != JsonToken.END_ARRAY) {
if (currentToken != JsonToken.VALUE_STRING) {
throw new JsonMappingException(p, "Not a string element!");
}
LocalDate localDate = LocalDate.parse(p.getValueAsString(), formatter);
list.add(localDate);
currentToken = p.nextToken();
}
return list.toArray(new LocalDate[0]);
}
}
And I changed the field annotation to be #JsonDeserialize(using = CustomLocalDateArrayDeserializer.class).
You can work on it to iterate & improve over it, make it read&respect #JsonFormat annotation and so on, if you think it is worth the effort.
I suspect looking at your code and your json model it is trying to convert to an array using a deserializer that is defined for one object. It simple terms you are trying to convert a single item to an array which it cant parse. You could Try a list of LocalDate instead. Something Like:
List<LocalDate> skip;
You might even need to create your own Deserializer based on the date serializer.
Just first glance: are actually json objects in your json array or just Strings as you showed? This should be something like this:
{
"skip": [
"key1":"01/01/2019",
"key2":"26/01/2019"
]
}
To the type date in cassandra database I would like to insert a value.
I tried with types java.util.Date and com.datastax.driver.core.LocalDate.
Both ways don't work for me.
For LocalDate error:
"JSON parse error: Can not construct instance of com.datastax.driver.core.LocalDate: no String-argument constructor/factory method to deserialize from String value (''); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.datastax.driver.core.LocalDate: no String-argument constructor/factory method to deserialize from String value ('')\n at [Source: java.io.PushbackInputStream#4d549b00; line: 10, column: 25] (through reference chain: com.comarch.programs.dtos.ProgramDto[\"prgStartDate\"])",
Date error:
"Expected 4 byte long for date (8); nested exception is com.datastax.driver.core.exceptions.InvalidQueryException: Expected 4 byte long for date (8)"
You can do the following way:
private Date accessDate;
#Transient
private Date activeDate;
public Date getActiveDate() {
return activeDate;
}
public void setActiveDate(Date activeDate) {
SimpleDateFormat sp1 = new SimpleDateFormat("yyyyy-MM-dd hh:mm:ss+0000");
String strDate = sp1.format(activeDate);
try {
this.activeDate = sp1.parse(strDate);
setAccessDate(new java.sql.Timestamp(this.activeDate.getTime()));
} catch (ParseException e) {
e.printStackTrace();
}
}
Use a transient data to format the date accordingly and set the date using java.sql.Timestamp
I'm trying to take an XML String and deserialize it into an object. I keep getting this exception though:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of javax.xml.datatype.XMLGregorianCalendar from String value '22:32:00': not a valid representation (error: Failed to parse Date value '22:32:00': Unparseable date: "22:32:00")
When it gets to this line:
xmlMapper.readValue(xml, clazz);
My XML contains:
<MyXML>
<Event>
<Time>22:32:00</Time>
</Event
</MyXML>
My object class member variable is:
#XmlElement(name = "Time", required = true)
#XmlSchemaType(name = "time")
#JsonProperty("Time")
#JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+0100")
protected XMLGregorianCalendar time;
Is there anything wrong with this configuration that would cause the above exception?