0

I'm referring this tutorial to learn the basics of Jackson, but badly tumbled into this.

This is the exception:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `hello.Car` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
    at [Source: (String)"{"color":"Black","type":"BMW"}"; line: 1, column: 2]

This is the class:

@Builder
@Data
@AllArgsConstructor
public class Car implements Serializable {
    private String color;
    private String type;
}

And this is the parsing logic:

@Service
public class HelloService {
    public void testJackson() throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        String json1 = "{\"color\":\"Black\",\"type\":\"BMW\"}";
        Car car1 = objectMapper.readValue(json1, Car.class);
    }
}

F.Y.I I'm using Jackson and Lombok:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.4</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.20</version>
        <scope>provided</scope>
    </dependency>

What's really the matter here. Please share some ideas.

UPDATE 2018-05-10 @Hemant Patel, thanks. Just added the @NoArgsConstructor, like a magic. It works as expected. I will look into it to find out what's really going on.

@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Car implements Serializable {
    String color;
    String type;
}

B.T.W Thanks @Thomas and @Alex, I checked these two posts but I really don't think the real cause lies in the relationship with Lombok.

Hearen
  • 7,420
  • 4
  • 53
  • 63
  • Possible duplicate of [Can't make Jackson and Lombok work together](https://stackoverflow.com/questions/39381474/cant-make-jackson-and-lombok-work-together) – Alex Shesterov May 09 '18 at 12:50
  • 1
    add @NoArgsConstructor as well – Hemant Patel May 09 '18 at 12:52
  • 1
    Possible duplicate of [Immutable Lombok annotated class with Jackson](https://stackoverflow.com/questions/49999492/immutable-lombok-annotated-class-with-jackson) – Thomas Fritsch May 09 '18 at 14:32
  • What is going on is that what Jackson really do is first instantiate the class and then sets it's values. It actually needs a constructor with no args to do that. Only after the class is instantiated that Jackson start setting the values of it's fields. If your fields were private you would need to create the getter and setter for it to work as well. – ygorazevedo May 10 '18 at 15:05
  • @Ygor Thanks, but do you have some doc to support your point? I `added` the `setters` and `getters` but they just do not work. Only the `@NoArgsConstructor` really does the trick. – Hearen May 10 '18 at 15:09
  • 1
    "Construction of mapper instances proceeds either via no-arguments constructor...". You can see it on https://github.com/FasterXML/jackson-databind/blob/master/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java – ygorazevedo May 10 '18 at 15:25
  • If you pay close attention to the Baeldung tutorial you are referring to, you'll see that the Car class has the default no args contructor and since it's fields are private it has the getter and setter as well. – ygorazevedo May 10 '18 at 15:32
  • @Hearen when you annotate a class with `@AllArgsConstructor` it won't have the default constructor anymore because on compilation time Lombok will implement a constructor with all args on your class. You can check it on your `.class` on the `target` folder. Wich means the class will no longer have the default constructor and you will have to explicitly implement it or also annotate the class with `@NoArgsConstructor` – ygorazevedo May 10 '18 at 15:35
  • @Ygor I just read its source and locate the issue but more easily with link you provided for Jackson. I was so blind to ignore the very beginning of it. Thank you so much – Hearen May 10 '18 at 15:38

2 Answers2

1

After long search, I found out this from its official API documentation:

public ObjectMapper()

Default constructor, which will construct the default JsonFactory as necessary, use SerializerProvider as its SerializerProvider, and BeanSerializerFactory as its SerializerFactory. This means that it can serialize all standard JDK types, as well as regular Java Beans (based on method names and Jackson-specific annotations), but does not support JAXB annotations.

As we know, what is the Java Beans (based on this post):

A JavaBean is just a standard

  1. All properties private (use getters/setters)
  2. A public no-argument constructor
  3. Implements Serializable.
Community
  • 1
  • 1
Hearen
  • 7,420
  • 4
  • 53
  • 63
0

Jackson requires default constructor and setters and gettes for json to class conversion. Change your Car class to

public class Car implements Serializable {
private String color;
private String type;


public Car() {
}


public String getColor() {
    return color;
}

public void setColor(String color) {
    this.color = color;
}

public String getType() {
    return type;
}

public void setType(String type) {
    this.type = type;
}
}
Kushagra Misra
  • 461
  • 1
  • 7
  • 15
  • Thanks for the reply but as you can see I am using `Lombok`, it will be much easier to use `@NoArgsConstructor` directly to achieve the same effect. – Hearen May 10 '18 at 15:40