1
votes

I am quite new to Spring. I am having a JSON parsing error when I try a POST method in Postman. Basically, I have a class that I want to call in another one in the form of a list.

I have an abstract entity that I use for classes, then I have a tag class;

@Entity
@Data
@EqualsAndHashCode(callSuper = true)
public class Tag extends AbstractEntity {

    @Column (nullable = false)
    private String tag;

And I have a question class:

@Entity
@Data
@EqualsAndHashCode(callSuper = true)
public class Question extends AbstractEntity {

    @Column (nullable = false)
    private String title;
    @Column (nullable = false)
    private String content;
    @OneToMany
    @Column (nullable = false)
    private List<Tag> tag;

Here is my controller:

@RestController
@RequestMapping("v1/enquiry")
public class EnquiryController {

    @Autowired
    private QuestionRepository questionRepository;

    @PostMapping
    public ResponseEntity<Question> createEnquiry(@RequestBody Question question) {
        if (question.getTitle() == null | question.getContent() == null) {
            throw new BadRequest("Please fill in the required fields!");
        }

        Question enq = questionRepository.save(question);
        return ResponseEntity.ok().body(enq);
    }

When I do a POST method with:

{ 
   "title": "question",
   "content": "cogito",
   "tag": ["java", "rest"]
}

I get the following error. I quite tried all of the suggestions to similar conditions posted around. None of them worked. What am I doing wrong?

"message": "JSON parse error: Cannot construct instance of com.mockup.mockupapi.model.Tag (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('java'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of com.mockup.mockupapi.model.Tag (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('java')\n at [Source: (PushbackInputStream); line: 4, column: 10] (through reference chain: com.mockup.mockupapi.model.Question[\"tag\"]->java.util.ArrayList[0])",


SOLVED

Thanks to clues in the commentary, I changed the array format in JSON, and added CascadeType to OneToMany call. I used .PERSIST, however, .ALL works as well.

The JSON format:

{ 
   "title": "question",
   "content": "cogito",
   "tag": [{"tag":"java"},{"tag": "rest"}]
}

The Question class:

@Entity
@Data
@EqualsAndHashCode(callSuper = true)
public class Question extends AbstractEntity {

    @Column (nullable = false)
    private String title;
    @Column (nullable = false)
    private String content;
    @OneToMany(cascade = CascadeType.PERSIST)
    @Column (nullable = false)
    private List<Tag> tag;
1
What happens if you add a @NoArgsConstructor to Tag?user991710
I tried, however, I still get the same error, with the same message output. @user991710emrahyergin
Change your JSON to this "tag":[{"tag":"java"},{"tag":"rest"}]. Specifically for that tag key.GnanaJeyam
I actually tried versions like "tag":{"java","rest"} and other possible versions. However, this one throws a IllegalStateException error: save the transient instance before flushing. @gnanajeyam95emrahyergin
Then add cascade type to ur one to many mappingGnanaJeyam

1 Answers

1
votes

Please change your JSON structure.

{ "title": "question", "content": "cogito", "tag": [{"tag":"java"},{"tag": "rest"}] }

Also add cascade in your mapping.

@OneToMany (cascade = CascadeType.ALL)
 @Column (nullable = false) 
 private List<Tag> tag;