Why jackson is not serializing this? - jackson

#Data
public class IdentificacaoBiometricaDto {
private Integer cdIdentifBiom;
private String nrMatricula;
private String deImpressaoDigital;
private Integer cdFilialAtualizacao;
}
I am using retrofit 2.6.1, jackson 2.9.9 and lombok 1.8.10.
The exception is:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class br.com.clamed.modelo.loja.dto.central.IdentificacaoBiometricaDto and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:313)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:400)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1392)
at com.fasterxml.jackson.databind.ObjectWriter._configAndWriteValue(ObjectWriter.java:1120)
at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsBytes(ObjectWriter.java:1017)
at retrofit2.converter.jackson.JacksonRequestBodyConverter.convert(JacksonRequestBodyConverter.java:34)
at retrofit2.converter.jackson.JacksonRequestBodyConverter.convert(JacksonRequestBodyConverter.java:24)
at retrofit2.ParameterHandler$Body.apply(ParameterHandler.java:355)
... 14 more
The object mapper:
return new ObjectMapper().registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule())
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
I am setting all fields, when passing it to a request body, retrofit fails because jackson could not serialize the object.
Retrofit call:
#POST("/usuario/v1.0/cadastraBiometria")
Call<IdentificacaoBiometricaDto> cadastraBiometria(#Body IdentificacaoBiometricaDto identificacaoBiometricaDto);
Rest service:
#RestController
#RequestMapping("/usuario")
public class UsuarioController {
#PostMapping(value = "/v1.0/cadastraBiometria")
public ResponseEntity<IdentificacaoBiometricaDto> cadastraBiometria(#RequestBody IdentificacaoBiometricaDto identificacaoBiometricaDto) {
}
}
Update:
If I change the retrofit converter to Gson it works;
If I serialize it using Jackson directly, it works;
Removing lombok makes no difference;

Found the problem. The biometric reader library was causing this. For some reason it's incompatible with openjdk-11 and is causing all sort of unrelated problems.
Yes, very weird. But the lib is very poorly done.

Related

#Cacheable annotation cannot work as expected when deserialize beans with LocalDateTime type property

I found that the annotation #Cacheable cannot work when the method returns a Java Bean type, this is the complete description:
I annotated #Cacheable on a method to use spring cache:
#Cacheable(cacheNames="userCache", key="#userId")
public User getUser(long userId){
return userRepository.getUserById(userId);
}
And the User class like this:
public class User{
Long userId;
String username;
#JsonSerialize(using = LocalDateTimeSerializer.class)
#JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime birthDateTime;
}
As you can see, I annotated the relating Jackson annotations to make Jackson deserialization for LocalDateTime types work, and this is the related dependency in pom.xml:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.12.5</version>
</dependency>
After that, I call the #Cacheable method getUser like this:
User user = userCache.getUser(1L);
and there throws an exception:
org.redisson.client.RedisException: Unexpected exception while processing command
at org.redisson.command.CommandAsyncService.convertException(CommandAsyncService.java:326)
at org.redisson.command.CommandAsyncService.get(CommandAsyncService.java:123)
at org.redisson.RedissonObject.get(RedissonObject.java:82)
...blabla
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type java.time.LocalDateTime not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling at [Source: (io.netty.buffer.ByteBufInputStream); line: 1, column: 101] (through reference chain: com.stackoverflow.domain.User["birthDateTime"]) at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1764)
at com.fasterxml.jackson.databind.deser.impl.UnsupportedTypeDeserializer.deserialize(UnsupportedTypeDeserializer.java:36)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
3.Before I use the #Cacheable, there is no problem if I get the User from database straightly. But when I begin to use #Cacheable, it always throws the exception above, no matter if I configured those Jackson deserialization for LocalDateTime. Is #Cacheable cannot work well with Java Bean with LocalDateTime property, or just my configuration of Jackson is wrong?
I had the same problem. Spring Cache doesn't use the implicit ObjectMapper used by other Spring components.
Include the module, you already did that.
Create a configuration which will override the default Spring Cache Configuration:
#Configuration
#EnableCaching
public class CacheConfiguration {
#Bean
public RedisSerializationContext.SerializationPair<Object> serializationPair() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule())
.activateDefaultTyping(
objectMapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.EVERYTHING,
JsonTypeInfo.As.PROPERTY
);
return RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapper));
}
#Bean
public RedisCacheConfiguration redisCacheConfiguration(
#Value("${cache.default-ttl-in-seconds}") Integer ttl,
RedisSerializationContext.SerializationPair<Object> serializationPair
) {
return RedisCacheConfiguration.defaultCacheConfig()
.disableCachingNullValues()
.entryTtl(Duration.ofSeconds(ttl))
.serializeValuesWith(serializationPair);
}
}

Register JodaModule in Jax-RS Application

I'm writing a Jax-RS application using Jersey, and Jackson2 under the hood to facilitate JSON i/o. The service itself works fine, but I'd like to improve it by having the Jackson mapper automagically serialize/deserialize date and date-times to JodaTime objects.
I'm following the documentation here and have added the relevant jars, but I'm lost on this instruction:
Registering module
To use Joda datatypes with Jackson, you will first need to register the module first (same as with all Jackson datatype modules):
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
I've tried to do this in the custom class that extends jax.ws.rs.core.Application, but I'm not at all confident in that solution. I'm currently getting this error:
Can not instantiate value of type [simple type, class org.joda.time.DateTime] from String value ('2014-10-22'); no single-String constructor/factory method
at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream#3471b6d5; line: 7, column: 25]
Other than the general impression that this module registration needs to happen at application (servlet?) startup, I have no idea what to do with this information. Do I need to annotate a custom class with something in particular to have it picked up ? Should I be extending some class ?
The examples I find on StackOverflow usually stick it in main() and call the mapper directly, but I'm relying on Jackson Databinding so the examples aren't relevant. Any direction is appreciated.
You'll basically want to create/configure/return the ObjectMapper in a ContextResolver. Something like
#Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
final ObjectMapper mapper = new ObjectMapper();
public ObjectMapperContextResolver() {
mapper.registerModule(new JodaModule());
}
#Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
If you are using package scanning to discover your resources, then the #Provider annotation should allow this class to be discovered and registered also.
Basically what happens, is the the MessageBodyReader and MessageBodyWriter provided by Jackson, used for unmarshalling and marshalling, respectively, will call the getContext method in the ContextResolver, to determine the ObjectMapper to use. The reader/writer will pass in the class (in a reader it will be the type expected in a method param, in a writer it will be the type returned as-a/in-a response), meaning we are allowed to use differently configured ObjectMapper for different classes, as seen here. In the above solution, it is used for all classes.

JsonIgnoreProperties not working

I have the following simple class:
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
#JsonIgnoreProperties({ "thirdField" })
public class Message {
private TypeA type;
private String producer;
//Getters and Setters
}
in my test class
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Test {
public void testMethd() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.USE_ANNOTATIONS, true);
Class<T> instanceType = Message.class;
String msgBody = "{\"producer\": \"clientApp\", \"type\": \"aType\", \"thirdField\": []}";
objectMapper.readValue(msgBody, instanceType);
}
}
All I am trying to do is to convert the above json string into Message class and ignore the 'thirdField'. But I keep getting
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "thirdField" (class Message), not marked as ignorable (2 known properties: , "type", "producer"])
You've mixed different versions of Jackson.
Notice that you import JsonIgnoreProperties from org.codehaus.jackson.annotate (version 1.x)
while you're using ObjectMapper from com.fasterxml.jackson.databind (version 2.x).
Try using the last Jackson version (2.4):
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
#JsonIgnoreProperties({"id"})
Here you can find an example where it's implement using version 2.4:
http://www.ibm.com/developerworks/java/library/j-hangman-app/index.html
I found a Solution to this.
Try to add
#JsonSerialize(include= JsonSerialize.Inclusion.NON_EMPTY)
About your class
#JsonSerialize(include= JsonSerialize.Inclusion.NON_EMPTY)
class ResponseModel {
//your properties here
#JsonIgnoreProperties("messageList","contactList","sender")
var contactList= ArrayList<ContactModel>()
}
That will solve your issue buddy.
It didn't work for me any of the above answers, i found a workaround that I have reinitialized the object and values (copied the object).

Jackson unrecognized field exception but field is in JSON

I am using Spring Integration to consume a message with a JSON Payload.
In my spring context I have
<integration:channel id="jsonToMyMessageConverterChannel"/>
<integration:json-to-object-transformer
type="com.acme.messaging.message.MyMessage"
input-channel="jsonToMyMessageConverterChannel"
output-channel="myMessageUpdateChannel"/>
My message related objects are:
MyMessage.java
#JsonIgnoreProperties(ignoreUnknown=true)
public class MyMessage {
#JsonProperty
private String timestamp;
#JsonProperty("msgs")
private List<Message> messages;
// Getters and Setters...
}
Message.java
#JsonIgnoreProperties(ignoreUnknown=true)
public class Message {
#JsonProperty
private Integer msgId;
#JsonProperty("msgText")
private String text;
// Getters and Setters...
}
When the json transformer attempts to convert the message to an object it fails with
Caused by: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "msgs" (Class com.acme.messaging.message.MyMessage), not marked as ignorable
The JSON payload definitely has msgs which is an array that has objects which represent the Message.java class.
Can any one suggest reasons why the exception occurs given that the JSON has the field that is being complained about and the class itself is also annotated to ignore unknown fields?
Update
After some debugging it looks like the #JsonProperty("msgs") annotations aren't being use, for some reason.
This works fine for me...
#Test
public void test() throws Exception {
MyMessages mm = new MyMessages();
MyMessage m = new MyMessage();
m.setMsgId(1);
m.setText("foo");
mm.setMessages(Arrays.asList(m));
mm.setTimestamp("123");
#SuppressWarnings("deprecation")
ObjectToJsonTransformer otjt = new ObjectToJsonTransformer(new ObjectMapper());
Message<?> message = new GenericMessage<MyMessages>(mm);
message = otjt.transform(message);
System.out.println(message);
#SuppressWarnings("deprecation")
JsonToObjectTransformer<MyMessages> jtot = new JsonToObjectTransformer<MyMessages>(MyMessages.class, new ObjectMapper());
message = jtot.transform(message);
mm = (MyMessages) message.getPayload();
System.out.println(mm.getTimestamp());
System.out.println(mm.getMessages().get(0).getText());
}
(I changed your classnames slightly to avoid colliding with Message<?>)
Resulting in...
[Payload={"timestamp":"123","msgs":[{"msgId":1,"msgText":"foo"}]}][Headers={timestamp=1373997151738, id=f2425f36-a500-4aee-93a4-e7e0240ce0f1, content-type=application/json}]
123
foo
Do you have both jackson 1.x (codehaus) and 2.x (fasterxml) on the classpath, and using Spring Integration 3.0.0?
If they're both on the classpath, SI will use Jackson 2.x, by default, (which won't understand 1.x annotations).
Or, I guess - are you using Jackson2 (fasterxml) annotations? Spring Integration 2.x uses Jackson 1 (codehaus).
EDIT:
In order to support both versions of Jackson, you can annotate the class with both annotations...
#JsonProperty("msgs")
#com.fasterxml.jackson.annotation.JsonProperty("msgs")
public List<MyMessage> messages;

Serialization issue with CommonsMultipartFile

my bean has folliwng snippet
#JsonIgnore
private List<MultipartFile> fileData;
#XmlTransient
public List<MultipartFile> getFileData() {
return fileData;
}
I et this error upon a file upload
org.codehaus.jackson.map.JsonMappingException: No serializer found for class java.io.FileDescriptor and
no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) )
(through reference chain: com.commands.MyCommand["fileData"]->
java.util.ArrayList[0]->org.springframework.web.multipart.commons.CommonsMultipartFile["fileItem"]->
org.apache.commons.fileupload.disk.DiskFileItem["inputStream"]->java.io.FileInputStream["fd"])
I read that if i used #JsonIgnore then I may be able to avoid this error, but this does not seem to be the case for me.
even though my getter was marked with #XMlTransient, seemed the jackson was still looking for #JsonIgnore and upon adding it, things worked as expected.