web-dev-qa-db-fra.com

Erreur d'analyse JSON: impossible de construire une instance de io.starter.topic.Topic

J'apprenais Spring Boot et j'ai fait une démo, mais quand j'ai POST) une demande d'ajout d'un objet, cela n'a pas fonctionné!

Le message d'erreur est:

{
    "timestamp": 1516897619316,
    "status": 400,
    "error": "Bad Request",
    "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
    "message": "JSON parse error: Can not construct instance of io.starter.topic.Topic: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of io.starter.topic.Topic: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)\n at [Source: Java.io.PushbackInputStream@1ff3f09a; line: 2, column: 9]",
    "path": "/topics/"
}

Mon entité:

public class Topic {
    private String id;
    private String name;
    private String author;
    private String desc;

    public Topic(String id, String name, String author, String desc) {

        this.id = id;
        this.name = name;
        this.author = author;
        this.desc = desc;
    }
    //getters and setters

Mon contrôleur:

public class TopicController {

    @Autowired
    private TopicService topicService;


    @RequestMapping(value = "/topics", method = RequestMethod.POST)
    public void addTopic(@RequestBody Topic topic) {
        topicService.addTopic(topic);
    }

Mon service:

@Service
public class TopicService {
    private List<Topic> topics = new ArrayList<>(Arrays.asList(
            new Topic("1", "topic1", "Martin", "T1"),
            new Topic("2", "topic2", "Jessie", "T2")  
            ));



    public void addTopic(Topic topic) {

        topics.add(topic);
    }

}

Mon json:

{
    "id": "3",
    "name": "topic3",
    "author": "Jessie3",
    "desc": "T3"
}

S'il vous plaît aider!

13
hackerang

Aux fins de désérialisation, Topic doit avoir un constructeur zéro argument.

Par exemple:

public class Topic {
    private String id;
    private String name;
    private String author;
    private String desc;

    // for deserialisation
    public Topic() {}    

    public Topic(String id, String name, String author, String desc) {    
        this.id = id;
        this.name = name;
        this.author = author;
        this.desc = desc;
    }

    // getters and setters

}     

C'est le comportement par défaut de la bibliothèque Jackson .

21
glytching

Vous devez annoter le constructeur avec @JsonCreator :

Les annotations de marqueur peuvent être utilisées pour définir les constructeurs et les méthodes de fabrique comme méthodes à utiliser pour instancier de nouvelles instances de la classe associée.

REMARQUE: lorsque vous annotez des méthodes de création (constructeurs, méthodes d'usine), la méthode doit être:

  • Méthode constructeur/fabrique à un seul argument sans JsonProperty annotation pour l'argument: si tel est le cas, il s'agit du "créateur du délégué", auquel cas Jackson associe d'abord JSON au type du argument, puis appelle le créateur. Ceci est souvent utilisé en conjonction avec JsonValue (utilisé pour la sérialisation).
  • Méthode constructeur/fabrique où chaque argument est annoté avec soit JsonProperty ou JacksonInject , pour indiquer le nom de la propriété à laquelle se lier

Notez également que toutes les JsonProperty annotations doivent spécifier le nom réel (PAS une chaîne vide pour "défaut"), sauf si vous utilisez l'un des modules d'extension capables de détecter le nom du paramètre; ceci parce que les versions par défaut du JDK antérieures à 8 n'ont pas été en mesure de stocker et/ou de récupérer les noms de paramètres à partir de bytecode. Mais avec JDK 8 (ou à l'aide de bibliothèques auxiliaires telles que Paranamer ou d'autres langages JVM tels que Scala ou Kotlin), la spécification du nom est facultative.

Comme ça:

@JsonCreator
public Topic(@JsonProperty("id") String id, @JsonProperty("name") String name,
             @JsonProperty("author") String author, @JsonProperty("desc") String desc) {
    this.id = id;
    this.name = name;
    this.author = author;
    this.desc = desc;
}
9
Andreas