JsonMappingException: не найден подходящий конструктор для типа [простой тип, класс]: невозможно создать экземпляр объекта JSON - PullRequest
402 голосов
/ 02 октября 2011

При попытке получить и обработать JSON-запрос появляется следующая ошибка:

org.codehaus.jackson.map.JsonMappingException: не найден подходящий конструктор для типа [простой тип, классcom.myweb.ApplesDO]: невозможно создать экземпляр объекта JSON (нужно добавить / включить информацию о типе?)

Вот JSON, который я пытаюсь отправить:

{
  "applesDO" : [
    {
      "apple" : "Green Apple"
    },
    {
      "apple" : "Red Apple"
    }
  ]
}

В Controller у меня есть следующая сигнатура метода:

@RequestMapping("showApples.do")
public String getApples(@RequestBody final AllApplesDO applesRequest){
    // Method Code
}

AllApplesDO - это оболочка ApplesDO:

public class AllApplesDO {

    private List<ApplesDO> applesDO;

    public List<ApplesDO> getApplesDO() {
        return applesDO;
    }

    public void setApplesDO(List<ApplesDO> applesDO) {
        this.applesDO = applesDO;
    }
}

ApplesDO:

public class ApplesDO {

    private String apple;

    public String getApple() {
        return apple;
    }

    public void setApple(String appl) {
        this.apple = apple;
    }

    public ApplesDO(CustomType custom){
        //constructor Code
    }
}

Я думаю, чтоДжексон не может преобразовать JSON в объекты Java для подклассов.Пожалуйста, помогите с параметрами конфигурации для Джексона для преобразования JSON в объекты Java.Я использую Spring Framework.

РЕДАКТИРОВАТЬ: Включена основная ошибка, которая вызывает эту проблему в приведенном выше примере класса - Пожалуйста, посмотрите принятый ответ для решения.

Ответы [ 13 ]

532 голосов
/ 02 октября 2011

Итак, наконец я понял, в чем проблема.Это не проблема конфигурации Джексона, как я сомневался.

На самом деле проблема была в ApplesDO Класс:

public class ApplesDO {

    private String apple;

    public String getApple() {
        return apple;
    }

    public void setApple(String apple) {
        this.apple = apple;
    }

    public ApplesDO(CustomType custom) {
        //constructor Code
    }
}

Для создания класса был определен специальный конструкторэто конструктор по умолчанию.При вводе фиктивного конструктора ошибка исчезла:

public class ApplesDO {

    private String apple;

    public String getApple() {
        return apple;
    }

    public void setApple(String apple) {
        this.apple = apple;
    }

    public ApplesDO(CustomType custom) {
        //constructor Code
    }

    //Introducing the dummy constructor
    public ApplesDO() {
    }

}
363 голосов
/ 14 сентября 2014

Это происходит по следующим причинам:

  1. ваш внутренний класс должен быть определен как static

    private static class Condition {  //jackson specific    
    }
    
  2. Возможно, в вашем классе нет конструктора по умолчанию ( ОБНОВЛЕНИЕ: Кажется, это не так)

    private static class Condition {
        private Long id;
    
        public Condition() {
        }
    
        // Setters and Getters
    }
    
  3. Возможно, ваши сеттеры не определены должным образом или не видны (например, частный сеттер)

57 голосов
/ 26 ноября 2014

Я хотел бы добавить к этому другое решение, которое не требует фиктивного конструктора. Поскольку фиктивные конструкторы немного запутаны и, как следствие, сбивают с толку. Мы можем предоставить безопасный конструктор и, пометив аргументы конструктора, позволим Джексону определить соответствие между параметром конструктора и полем.

, поэтому следующее также будет работать. Обратите внимание, что строка внутри аннотации должна соответствовать имени поля.

import com.fasterxml.jackson.annotation.JsonProperty;
public class ApplesDO {

        private String apple;

        public String getApple() {
            return apple;
        }

        public void setApple(String apple) {
            this.apple = apple;
        }

        public ApplesDO(CustomType custom){
            //constructor Code
        }

        public ApplesDO(@JsonProperty("apple")String apple) {
        }

}
29 голосов
/ 17 сентября 2015

Когда я столкнулся с этой проблемой, это было результатом попытки использовать внутренний класс в качестве DO. Для создания внутреннего класса (молча) потребовался экземпляр окружающего класса, который не был доступен Джексону.

В этом случае перемещение внутреннего класса в собственный файл .java устранило проблему.

14 голосов
/ 08 октября 2018

Обычно эта ошибка возникает из-за того, что мы не создаем конструктор по умолчанию, но в моем случае проблема возникла только из-за того, что я использовал использованный класс объекта внутри родительского класса.Это потратило впустую весь мой день.

12 голосов
/ 29 декабря 2014

Правило большого пальца : Добавить конструктор по умолчанию для каждого класса, который вы использовали в качестве класса отображения.Вы пропустили это и проблема возникла!
Просто добавьте конструктор по умолчанию, и он должен работать.

10 голосов
/ 02 октября 2011

Можете ли вы проверить эту структуру.Если я правильно помню, вы можете использовать его следующим образом:

{
    "applesRequest": {
        "applesDO": [
            {
                "apple": "Green Apple"
            },
            {
                "apple": "Red Apple"
            }
        ]
    }
}

Во-вторых, добавьте конструктор по умолчанию для каждого класса, это также может помочь.

5 голосов
/ 03 мая 2017

Вы должны создать фиктивный пустой конструктор в нашем классе модели. Так что при отображении json он устанавливается методом сеттера.

4 голосов
/ 10 сентября 2016

Если вы начинаете аннотировать конструктор, вы должны аннотировать все поля.

Обратите внимание, что мое поле Staff.name отображается в "ANOTHER_NAME" в строке JSON.

     String jsonInString="{\"ANOTHER_NAME\":\"John\",\"age\":\"17\"}";
     ObjectMapper mapper = new ObjectMapper();
     Staff obj = mapper.readValue(jsonInString, Staff.class);
     // print to screen

     public static class Staff {
       public String name;
       public Integer age;
       public Staff() {         
       }        

       //@JsonCreator - don't need this
       public Staff(@JsonProperty("ANOTHER_NAME") String   n,@JsonProperty("age") Integer a) {
        name=n;age=a;
       }        
    }
3 голосов
/ 09 августа 2016

Вы должны понять, какие варианты есть у Джексона для десериализации.В Java имена аргументов метода отсутствуют в скомпилированном коде.Вот почему Джексон не может вообще использовать конструкторы для создания четко определенного объекта со всем уже установленным.

Итак, если есть пустой конструктор, а также есть сеттеры, он использует пустой конструктор и сеттеры.Если сеттеров нет, для этого используется некоторая темная магия (отражения).

Если вы хотите использовать конструктор с Джексоном, вы должны использовать аннотации, упомянутые @PiersyP в его ответе.Вы также можете использовать шаблон строителя.Если вы столкнулись с некоторыми исключениями, удачи.Обработка ошибок в Джексоне - это отстой, трудно понять этот бред в сообщениях об ошибках.

...