JsonMappingException: Không tìm thấy hàm tạo phù hợp cho loại [kiểu đơn giản, lớp]: không thể khởi tạo từ đối tượng JSON


388
73
Trần Hạnh Thảo
8 năm trước

Tôi gặp lỗi sau khi cố gắng nhận yêu cầu JSON và xử lý nó:

org.codehaus.jackson.map.JsonMappingException: Không tìm thấy hàm tạo phù hợp cho loại [loại đơn giản, lớp com.myweb.ApplesDO]: không thể khởi tạo từ đối tượng JSON (cần thêm / bật thông tin loại?)

Đây là JSON tôi đang cố gắng gửi:

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

Trong Trình điều khiển, tôi có chữ ký phương thức sau:

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

AllApplesDO là một trình bao bọc của ApplesDO:

public class AllApplesDO {

    private List<ApplesDO> applesDO;

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

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

TáoDO:

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
    }
}

Tôi nghĩ rằng Jackson không thể chuyển đổi JSON thành các đối tượng Java cho các lớp con. Vui lòng trợ giúp với các tham số cấu hình để Jackson chuyển đổi JSON thành Đối tượng Java. Tôi đang sử dụng Spring Framework.

EDIT: Bao gồm lỗi lớn gây ra vấn đề này trong lớp mẫu ở trên - Vui lòng xem câu trả lời được chấp nhận cho giải pháp.

Hữu ích 388 Yêu thích 73 Chia sẻ Viết bình luận 2
Không hữu ích

Tôi không thấy bất kỳ lớp con nào trong đoạn mã trên, đây có phải là mã bạn đang cố gắng hoặc bạn đang tạo ra một ví dụ đơn giản hơn?

Hữu ích 2 · Không hữu ích · Trả lời 0

Tôi đã thêm một câu trả lời với một số giải thích thêm về cách thức hoạt động. Về cơ bản, bạn cần nhận ra Java không giữ các tên đối số phương thức trong thời gian chạy.

Hữu ích 0 · Không hữu ích · Trả lời 0

12 Trả lời


520
Đặng Diệu Huyền
8 năm trước

Vì vậy, cuối cùng tôi nhận ra vấn đề là gì. Đây không phải là vấn đề cấu hình của Jackson như tôi nghi ngờ.

Trên thực tế, vấn đề là ở Lớp 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
    }
}

Có một hàm tạo tùy chỉnh được định nghĩa cho lớp làm cho nó trở thành hàm tạo mặc định. Giới thiệu một nhà xây dựng giả đã khiến lỗi biến mất:

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() {
    }

}
Hữu ích 520 Trả lời hay nhất Chia sẻ Viết bình luận 5
Không hữu ích

Bạn có thể sử dụng jackson với các lớp bên trong (lồng nhau), tuần tự hóa hoạt động tốt trong trường hợp này. Điều vấp ngã duy nhất là lớp bên trong phải được đánh dấu là "tĩnh" để khử lưu huỳnh hoạt động đúng. Xem exlanation

Hữu ích 171 · Không hữu ích · Trả lời 0

@Suman Tôi sẽ không gọi đây là một hàm tạo giả - nó chỉ là hàm tạo mặc định. Nó không chỉ hoàn toàn hợp lệ, mà còn được yêu cầu cho nhiều loại xử lý kiểu java bean. (Và, tất nhiên, nó làm tôi vấp ngã. :-))

Hữu ích 6 · Không hữu ích · Trả lời 0

Ai đó có thể vui lòng giải thích tại sao điều này xảy ra? Tôi đã có một lỗi rất giống nhau. Nghĩ rằng tất cả các nhà xây dựng đúng đã được đưa ra, nhưng không thể giải trừ. Nó chỉ hoạt động sau khi tôi thêm một hàm tạo giả, sau khi đọc bài viết này.

Hữu ích 3 · Không hữu ích · Trả lời 0

Nếu bạn không muốn thêm hàm tạo mặc định (ví dụ: khi bạn đang xử lý các đối tượng không thay đổi). Bạn sẽ phải cho biết nhà xây dựng hoặc phương thức nhà máy nào sẽ sử dụng để khởi tạo đối tượng bằng cách sử dụng chú thích JsonCreator.

Hữu ích 2 · Không hữu ích · Trả lời 0

Tôi có thể hỏi CustomType đến từ đâu không. Tôi đang thử một cấu trúc như thế này nhưng tôi hoàn toàn mới với Java.

Hữu ích 0 · Không hữu ích · Trả lời 0

352
Đỗ Thành Tín
5 năm trước

Điều này xảy ra vì những lý do sau:

  1. lớp bên trong của bạn nên được định nghĩa là tĩnh

    private static class Condition {  //jackson specific    
    }
  2. Có thể là bạn không có hàm tạo mặc định trong lớp của mình ( CẬP NHẬT: Điều này dường như không phải là trường hợp)

    private static class Condition {
        private Long id;
    
        public Condition() {
        }
    
        // Setters and Getters
    }
  3. Nó có thể là Setters của bạn không được xác định đúng hoặc không hiển thị (ví dụ: setter private)

Hữu ích 352 Chia sẻ Viết bình luận 5
Không hữu ích

lớp tĩnh tạo ra sự khác biệt trong trường hợp của tôi. Cảm ơn!

Hữu ích 94 · Không hữu ích · Trả lời 0

Vâng, kinh nghiệm của tôi là với Jackson 2.4.4: thực sự hàm tạo mặc định ẩn của Java là đủ. Bạn cần phải viết rõ ràng hàm tạo không có đối số chỉ khi bạn đã xác định các hàm tạo khác có tham số (nghĩa là khi Java không tạo ra hàm không có đối số cho bạn).

Hữu ích 5 · Không hữu ích · Trả lời 0

Lớp tĩnh cũng cứu ngày của tôi, chúc mừng!

Hữu ích 4 · Không hữu ích · Trả lời 0

Và tất nhiên, bạn không cần phải khai báo một hàm tạo mặc định không có đối số, Java sẽ làm điều đó cho bạn ! (Miễn là bạn không định nghĩa bất kỳ nhà xây dựng nào khác.)

Hữu ích 2 · Không hữu ích · Trả lời 0

Cũng với tôi, lớp tĩnh lưu trong ngày.

Hữu ích 2 · Không hữu ích · Trả lời 0

57
Trần Thu Phong
5 năm trước

Tôi muốn thêm một giải pháp khác cho vấn đề này mà không yêu cầu một nhà xây dựng giả. Vì các nhà xây dựng giả là một chút lộn xộn và sau đó khó hiểu. Chúng tôi có thể cung cấp một hàm tạo an toàn và bằng cách chú thích các đối số của hàm tạo, chúng tôi cho phép jackson xác định ánh xạ giữa tham số của hàm tạo và trường.

Vì vậy, sau đây cũng sẽ làm việc. Lưu ý chuỗi bên trong chú thích phải khớp với tên trường.

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) {
        }

}
Hữu ích 57 Chia sẻ Viết bình luận 5
Không hữu ích

Điều này hữu ích với tôi vì tôi muốn đối tượng của mình là bất biến, vì vậy một người xây dựng giả không phải là một lựa chọn.

Hữu ích 1 · Không hữu ích · Trả lời 0

Giải pháp này đã làm được mẹo. Tôi chỉ muốn đề cập đến những điều sau đây, tôi đã có một hàm tạo, nhưng tên của các tham số khác với các tham số thể hiện, vì vậy nó không thể được ánh xạ. Thêm chú thích đã giải quyết nó, nhưng đổi tên các tham số có lẽ cũng hoạt động.

Hữu ích 0 · Không hữu ích · Trả lời 0

Điều gì xảy ra nếu tham số constructor không có trong phản hồi? Nó có thể được tiêm theo cách khác?

Hữu ích 0 · Không hữu ích · Trả lời 0

Dữ liệu quan trọng duy nhất đang được gửi ở đây là String apple phản hồi.

Hữu ích 0 · Không hữu ích · Trả lời 0

Trong trường hợp của tôi, nó cũng yêu cầu thêm @JsonCreatorvào hàm tạo với @JsonProperty.

Hữu ích 0 · Không hữu ích · Trả lời 0

28
Lý Ðinh Lộc
4 năm trước

Khi tôi gặp phải vấn đề này, đó là kết quả của việc cố gắng sử dụng một lớp bên trong để phục vụ như là DO. Việc xây dựng lớp bên trong (âm thầm) yêu cầu một thể hiện của lớp kèm theo - vốn không có sẵn cho Jackson.

Trong trường hợp này, việc di chuyển lớp bên trong sang tệp .java của chính nó đã khắc phục sự cố.

Hữu ích 28 Chia sẻ Viết bình luận 1
Không hữu ích

Trong khi việc di chuyển lớp bên trong sang tệp .java của chính nó hoạt động, việc thêm công cụ sửa đổi tĩnh cũng giải quyết vấn đề như được đề cập trong câu trả lời của @ bludream.

Hữu ích 6 · Không hữu ích · Trả lời 0

13
Trịnh Mỹ Vân
1 năm trước

Nói chung, lỗi này xuất hiện do chúng tôi không tạo hàm tạo mặc định nhưng trong trường hợp của tôi Sự cố chỉ xảy ra do tôi đã tạo lớp đối tượng đã sử dụng bên trong lớp cha. Điều này đã lãng phí cả ngày của tôi.

Hữu ích 13 Chia sẻ Viết bình luận 1
Không hữu ích

Bạn đã cứu ngày của tôi, cảm ơn rất nhiều!

Hữu ích 3 · Không hữu ích · Trả lời 0

11
Trần Hải Nhi
5 năm trước

Quy tắc ngón tay cái : Thêm một hàm tạo mặc định cho mỗi lớp bạn đã sử dụng làm lớp ánh xạ. Bạn đã bỏ lỡ điều này và vấn đề phát sinh!
Đơn giản chỉ cần thêm constructor mặc định và nó sẽ hoạt động.

Hữu ích 11 Chia sẻ Viết bình luận 0
Không hữu ích

10
Nguyễn Quang Huy
8 năm trước

Bạn có thể vui lòng kiểm tra cấu trúc này. Nếu tôi nhớ chính xác, bạn có thể sử dụng nó theo cách này:

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

Thứ hai, vui lòng thêm hàm tạo mặc định cho mỗi lớp mà nó cũng có thể giúp ích.

Hữu ích 10 Chia sẻ Viết bình luận 4
Không hữu ích

Không làm việc: Bắt lỗi sau: "org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Trường không được nhận & quot; applesRequest & quot; (Lớp com.smartshop.dao.AllApplesDO), không được đánh dấu là có thể bỏ"

Hữu ích 0 · Không hữu ích · Trả lời 0

Trước đây, nó ít nhất không thông qua lỗi đối với AllApplesDO và chỉ ném cho lớp kèm theo .. bây giờ, nó ném cho chính lớp đầu tiên

Hữu ích 0 · Không hữu ích · Trả lời 0

Cần một constructor mặc định. Cảm ơn!

Hữu ích 0 · Không hữu ích · Trả lời 0

không nên chọn điều này làm câu trả lời ĐÚNG?

Hữu ích 0 · Không hữu ích · Trả lời 0

5
Hoàng Vũ Anh
3 năm trước

Bạn phải tạo hàm tạo rỗng giả trong lớp mô hình của chúng tôi. Trong khi ánh xạ json, nó được thiết lập bằng phương thức setter.

Hữu ích 5 Chia sẻ Viết bình luận 0
Không hữu ích

4
Dương Quốc Việt
3 năm trước

Nếu bạn bắt đầu chú thích hàm tạo, bạn phải chú thích tất cả các trường.

Lưu ý, trường Staff.name của tôi được ánh xạ tới "ANOTHER_NAME" trong chuỗi 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;
       }        
    }
Hữu ích 4 Chia sẻ Viết bình luận 0
Không hữu ích

3
Bùi Mỹ Khuyên
3 năm trước

Bạn phải nhận ra những lựa chọn nào Jackson có sẵn để khử lưu huỳnh. Trong Java, tên đối số phương thức không có trong mã được biên dịch. Đó là lý do tại sao Jackson thường không thể sử dụng các hàm tạo để tạo một đối tượng được xác định rõ ràng với mọi thứ đã được đặt.

Vì vậy, nếu có một hàm tạo rỗng và cũng có setters, nó sử dụng hàm tạo và setters rỗng. Nếu không có setters, một số phép thuật bóng tối (phản xạ) được sử dụng để làm điều đó.

Nếu bạn muốn sử dụng một hàm tạo với Jackson, bạn phải sử dụng các chú thích như được đề cập bởi @PiersyP trong câu trả lời của anh ấy. Bạn cũng có thể sử dụng một mô hình xây dựng. Nếu bạn gặp một số ngoại lệ, chúc may mắn. Xử lý lỗi trong Jackson hút thời gian lớn, thật khó để hiểu rằng sự vô nghĩa trong các thông báo lỗi.

Hữu ích 3 Chia sẻ Viết bình luận 2
Không hữu ích

Lý do bạn cần một "hàm tạo đối số mặc định" FooClass () có thể là do Spring tuân theo Đặc tả JavaBean, yêu cầu điều này hoạt động để tự động sắp xếp và sắp xếp lại khi sắp xếp và giải tuần tự hóa các đối tượng.

Hữu ích 0 · Không hữu ích · Trả lời 0

Chà, dù sao thì tuần tự hóa và giải tuần tự hóa Java thành luồng nhị phân không phải là câu hỏi gì. Vì vậy, thật tốt khi Jackson cung cấp nhiều mẫu được sử dụng với quá trình khử lưu huỳnh. Tôi đặc biệt thích mẫu xây dựng vì nó cho phép đối tượng kết quả là bất biến.

Hữu ích 0 · Không hữu ích · Trả lời 0

0
Hoàng Thông Tuệ
4 năm trước

Không có bộ nối tiếp / bộ giải mã jackson tùy chỉnh cũng có thể là vấn đề. Mặc dù đó không phải là trường hợp của bạn, nhưng nó đáng được đề cập.

Tôi đã đối mặt với ngoại lệ tương tự và đó là trường hợp.

Hữu ích 0 Chia sẻ Viết bình luận 0
Không hữu ích

0
Phạm Khả Ái
2 năm trước

Đối với tôi, điều này được sử dụng để làm việc, nhưng nâng cấp thư viện gây ra vấn đề này xuất hiện. Vấn đề là có một lớp học như thế này:

package example.counter;

import javax.validation.constraints.NotNull;

import lombok.Data;

@Data
public class CounterRequest {
    @NotNull
    private final Integer int1;

    @NotNull
    private final Integer int2;
}

Sử dụng lombok:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.0</version>
</dependency>

Rơi lại

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.10</version>
</dependency>

Đã khắc phục sự cố. Không chắc chắn tại sao, nhưng muốn ghi lại nó cho tương lai.

Hữu ích 0 Chia sẻ Viết bình luận 0
Không hữu ích

Trả lời của bạn

Xem trước nội dung