How to fix the error: cannot deserialize from Object value (no delegate- or Property-based Creator) using Spring Boot?

Asked

Viewed 3,560 times

1

I am trying to send a JSON to my Spring method for entry into the database but I get the following message:

JSON parse error:

Cannot construct instance of br.com.marketHubServer.model.Collaborator (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of br.com.marketHubServer.model.Collaborator (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: (PushbackInputStream); line: 6, column: 9]

I believe that the problem happens due to the inheritance of classes I am doing, because with other classes the error does not happen.

Class Profile:

@Entity(name="Profile")
@Inheritance(strategy = InheritanceType.JOINED)
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, 
        include=JsonTypeInfo.As.EXISTING_PROPERTY, property="type")
@JsonTypeName("profile")
@JsonSubTypes({
        @JsonSubTypes.Type(name="company", value=Company.class),
        @JsonSubTypes.Type(name="collaborator", value=Collaborator.class)})
public abstract class Profile {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Transient
    @JsonProperty("type")
    private final String type = "profile";

    @Column(unique = true, nullable = false, length = 255)
    private String emailAddress;

    @JsonIgnore
    private String password;

    @Transient
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String newPassword;

    @Column(nullable = false, length = 100)
    private String name;

    @ElementCollection(fetch = FetchType.EAGER)
    private List<String> permissions;

Company class:

@Entity
public class Company extends Profile {
    @Transient
    @JsonProperty("type") 
    private final String type = "company";

    @Column(nullable = false, length = 100)
    private String companyLegalName;

    @Column(nullable = false, length = 400)
    private String companyDescription;

    @Column(nullable = false, length = 14)
    private String companyCnpjCpf;

    @Column(nullable = false, length = 9)
    private String companyPhone;

Collaborating Class:

@Entity
public class Collaborator extends Profile { 
    @Transient
    @JsonProperty("type")
    private final String type = "collaborator";

    @Column(nullable = false, length = 11)
    private String collaboratorCpf;

Method to consist of database profile:

@RequestMapping(path = "/companies", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.CREATED)
    public Profile create(@AuthenticationPrincipal ProfileAut profileAut, @RequestBody Profile profile) throws Exception {
        profile.setId(0);

        Profile profileSave = companyDAO.save(profile);
        return profileSave;
    }

I am trying to save a contributor to the database through the following json:

{
    "emailAddress":"teste",
    "password":"teste2",
    "name":"teste3",
    "type":"collaborator",
    "collaboratorCpf": "teste"
}

No use of inheritance I was able to receive the object and store the data in the database without problems.

  • Make sure this article can help you: https://medium.com/consulner/lombok-tricks-and-common-mistakes-fbf0ed044c3c . Read from "Jackson serialisation and deserialisation".

  • Did you create the private builders in the Entities? Jackson needs the constructors.

  • I tried, but it still didn’t work.

2 answers

2


The recommended to develop the application avoiding the maximum possible inheritance prioritizing the compositions due to good practices and etc, you should reflect the impact of this structure, if this requirement is necessary because it really generates some more demands to generate the json.

To use the inheritance you must map using the spring objectMapper

ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping();
// ... seus profiles poulados

String jsonDataString = mapper.writeValueAsString(profiles);
mapper.readValue(jsonDataString, Profile.class);

another "problem" is that if you want to return the persisted objects you will need to deserialize or you must "reassemble the object".

Profile profiles = mapper.readValue(jsonDataString, Profile.class);
assertThat(profiles.get(0), instanceOf(Company.class));

reference post : https://www.baeldung.com/jackson-inheritance

ps: There is also a third way for relationship with various entities and with various heritages where queries are made by returning a Map<string,object> and thus reassembling in Dto’s with all the values that are needed.

-1

I’ve had this problem with Kotlin and fixed it using the code below.

@Configuration
open class JacksonMapper {

    @Bean
    open fun mapper(): ObjectMapper {
        val mapper = ObjectMapper()
        ...

        mapper.registerModule(KotlinModule())
        return mapper
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.