Kong / unirest-java

Unirest in Java: Simplified, lightweight HTTP client library.
http://kong.github.io/unirest-java/
MIT License
2.59k stars 593 forks source link

Parsing error with JSON containing a serialized Date #367

Closed Tazaf closed 4 years ago

Tazaf commented 4 years ago

Describe the bug Hi!

In a Spring Boot app, I'm calling an external custom API using Unirest, and I'm trying to parse the JSON response containing a serialized date (example below) into a custom class, which defines a member as a ZonedDateTime (example below). The response contains a parsingError whose value is a UnirestParsingException that have the following detailMessage:

com.google.gson.JsonSyntaxException: 
  java.lang.IllegalStateException:
    Expected BEGIN_OBJECT but was STRING at line 1 column 45 path $.createdAt

Here's an example of the API JSON response:

{
    "createdBy": "SqrsApp-no-user",
    "createdAt": "2020-05-25T08:57:12.872394+02:00",
    "id": 0123456789,
    "firstname": "Foo",
    "lastname": "Bar"
}

Here's an example of the class to which I'm asking Unirest to map to:

public class User {
    private String createdBy;
    private ZonedDateTime createdAt;
    private Long id;
    private String firstname;
    private String lastname;

    // Getters & Setters
}

And here's an excerpt of the method that tries to fetch that user:

public User fetchUser(Long userId) {
    GetRequest req = Unirest.get(BASE_URI, userId.toString()));
    HttpResponse<User> res = req.asObject(User.class);
    res.ifFailure(Error.class, this.errorHandler);
    return res.getBody();
}

Expected behavior I understand that the parsing error messages indicates that the GSON parser was expecting an object for the createdAt property in the JSON, since the targeted class defines a ZonedDateTime member, which is an object.

But dates are stringified as strings with well defined format. I don't think that the JSON response is at fault here.

I would expect the parser to be able to see that its indeed a date and that it could parse this into a proper ZonedDateTime object.

Am I missing something? Is this an issue with the GSON parser? Should I configure Unirest so that it uses Jackson instead?

Environmental Data - Java Version: ``` openjdk version "11.0.7" 2020-04-14 OpenJDK Runtime Environment (build 11.0.7+10-post-Ubuntu-2ubuntu218.04) OpenJDK 64-Bit Server VM (build 11.0.7+10-post-Ubuntu-2ubuntu218.04, mixed mode, sharing) ``` - Version: 3.4.00
ryber commented 4 years ago

So a ZonedDateTime is not a simple pojo type object and requires special serializers registered to it. The same applies to Jackson so I'm not sure switching to it would be any different (although maybe).

I'd like the default ObjectMapper to support standard java date types so I'll go ahead and add the helpers to it.

Tazaf commented 4 years ago

So a ZonedDateTime is not a simple pojo type object and requires special serializers registered to it.

Oh. I was suspecting something like that.

I'd like the default ObjectMapper to support standard java date types so I'll go ahead and add the helpers to it.

Well, that's very nice of you 😃

ryber commented 4 years ago

3.10.00 Adds native default support for various Java DateTime types for the built in object mapper. All types will serialize to ISO-8601. Parsing from json will attempt various ISO variants.

Here are some tests as examples: https://github.com/Kong/unirest-java/blob/main/unirest/src/test/java/kong/unirest/JsonObjectMapperTest.java

Tazaf commented 4 years ago

Awesome! Very much appreciated 👍