Search code examples
javaspring-bootexception

InvalidDefinitionException No serializer found in java for generic class


I have a generic class

@NoArgsConstructor
public class CustomData<T> {

}

Below is the class it is used.

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Recipient {
    @NotEmpty(message = "Please provide email details of recipient")
    public String email;
    public CustomData<?> custom_data;
}

Below is the payload I'm trying to use

"recipients": [
    {
      "custom_data": {},
      "email": "string"
    }
  ]

However I get an error saying com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class

Can someone please help? Thank you for your time


Solution

  • Please add the property SerializationFeature.FAIL_ON_EMPTY_BEANS= false to your object mapper like objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

    Or you can add this code to any class of springboot which have a @Configuration annotation on it.

    @Bean
    public ObjectMapper getMapper() {
    
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        return objectMapper;
    }
    

    Send Payload as

    {
        "custom_data": {},
        "email": "emailvalue"
    }
    

    Now I am supposing your API is like this:

    @PostMapping(value = "/show/recipient") /*  /preview-email-recipient*/
    public ResponseEntity<?> showRecipient(@Valid @RequestBody Recipient recipient){
        log.info(String.format("recipient received {%s} ",recipient.toString()));
    
        return new ResponseEntity<>(recipient,HttpStatus.OK);
    }
    

    curl call to the endpoint will be POST to a URL http://localhost:8080/show/recipient with request body as:

    {
        "customData": {},
        "email": "emailvalue"
    }
    

    response:

    {
        "customData": {},
        "email": "emailvalue"
    }
    

    The reason for failure:

    When you return your object i.e. (Recipient in this case) in response it is getting Serialized to JSON string using ObjectMapper which is used in spring's MessageConverter(i.e. Jackson2HttpMessageConverter) bean.

    Now the error is caused by how ObjectMapper serializes your class. Your class has 2 fields, 1 of type String and 1 of type JSONObject/GenericType. ObjectMapper when serializing fields, tries to find the corresponding serializer based on the field type. There are some out-of-the-box implementations of serializers for known types like String but for your custom type you either need to provide a serializer to ObjectMapper bean or have to disable serialization via configuration of set property SerializationFeature.FAIL_ON_EMPTY_BEANS to false.

    Now what does SerializationFeature.FAIL_ON_EMPTY_BEANS do??

        /**
         * Feature that determines what happens when no accessors are
         * found for a type (and there are no annotations to indicate
         * it is meant to be serialized). If enabled (default), an
         * exception is thrown to indicate these as non-serializable
         * types; if disabled, they are serialized as empty Objects,
         * i.e. without any properties.
         *<p>
         * Note that empty types that this feature has only effect on
         * those "empty" beans that do not have any recognized annotations
         * (like <code>@JsonSerialize</code>): ones that do have annotations
         * do not result in an exception being thrown.
         *<p>
         * Feature is enabled by default.
         */    
         public static final SerializationFeature FAIL_ON_EMPTY_BEANS
    

    So:
    1 way was to disable serialization on empty beans.
    2nd way you can annotate CustomData class with @JsonSerialize. You are provinding the mapper which serializer you have to used for this param. Make CustomData class as:

    @NoArgsConstructor
    @JsonSerialize
    public class CustomData<T> {}