Reputation: 580
I have read many postings on here on JSON parsing to Java objects and have had my parsing working just fine until I introduced LocalDateTime. I have tried to using the Java 8 parser, the JSR310 module and to build a customization - below describing the roadblocks on each. Any help would be appreciated!
This is my JSON string, creating by Jackson from another POJO:
{"validEscortsWTheirSpecReqs":"MAYBE",
"modifiedDateTimeNeedToBeThere":
{"dayOfMonth":6,"dayOfWeek":"MONDAY","month":"FEBRUARY","year":2017,
"hour":10,"minute":1,"second":24,"nano":0,"dayOfYear":37,"monthValue":2,
"chronology":{"id":"ISO","calendarType":"iso8601"}
}
}
which generates
com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (START_OBJECT), expected VALUE_STRING: Expected array or string. at
...
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270)
at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:1376)
at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer.deserialize(LocalDateTimeDeserializer.java:118)
at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer.deserialize(LocalDateTimeDeserializer.java:39)
...
called from:
ComputeArrive response = mapper.readValue(responseString, ComputeArrive.class);
Response has the following fields:
Logger logger // should not be mapped by JSON, no getters/setters static final long serialVersionUID = 1L; // " String validEscortsWTheirSpecReqs = "YES" // want mapped LocalDateTime modifiedDateTimeNeedToBeThere // want mapped
I have probably registered too many modules by now, adding them in to try to get it to parse:
mapper.findAndRegisterModules();
//mapper .registerModule(new ParameterNamesModule());
mapper.registerModule(new Jdk8Module());
mapper.registerModule(new JavaTimeModule());
mapper.registerModule(new JSR310Module());
So I have tried to add Spring Boot dependencies to my project and write a customizer for JSR310 (which seems unecessary given the modules above):
@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
return objectMapper;
}
}
My application has numerous dependencies so I did not want to make anything a "parent" of it and added the following dependencies. However, the class "Jackson2ObjectMapperBuilder" is not being found so the above does not compiles with these dependencies:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
I am not finding a lot of documentation for "Jackson2ObjectMapperBuilderCustomizer" which may be a replacement for "Jackson2ObjectMapperBuilder" - which could be the issue. Please note that the class above is not instantiated by me because I assume Spring instantiates it.
Any thoughts on how to parse my response would be most appreciated!
Upvotes: 13
Views: 23977
Reputation: 494
As @Tobias said use JavaTimeModule
will solve the problem.
Add the JSR310 dependency in your pom xml to allow Jackson to be able to recognize Java 8 Date&Time API data types :
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
You can now use JavaTimeModule
in you Jackson configuration like this :
@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
return objectMapper;
}
}
You should use this configuration to serialize and deserialize LocalDate or other Java 8 Date&Time API data types.
Upvotes: -1
Reputation: 9
I think the problem is the parsing of the LocalDate, try this:
{
"validEscortsWTheirSpecReqs":"MAYBE",
"modifiedDateTimeNeedToBeThere":[6,2,2017]
}
day, month, year represented by integers.
Upvotes: 1
Reputation: 7380
For me, this problem was solved by adding the JavaTimeModule
to the Jackson2ObjectMapperBuilder
like this:
@Configuration
public class MyConfiguration {
@Bean
@Primary
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
return builder.modulesToInstall(new JavaTimeModule());
}
}
Then Spring uses this mapper with the registered module.
Upvotes: 7