JsonMappingException: [simple type, class] türü için uygun bir kurucu bulunamadı: JSON nesnesinden örnek oluşturulamıyor


438

Bir JSON isteği almak ve işlemek için çalışırken aşağıdaki hatayı alıyorum:

org.codehaus.jackson.map.JsonMappingException: [simple type, class com.myweb.ApplesDO] türü için uygun bir kurucu bulunamadı: JSON nesnesinden örnek oluşturulamıyor (tür bilgisi eklemeniz / etkinleştirmeniz mi gerekiyor?)

İşte göndermeye çalıştığım JSON:

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

Denetleyici'de aşağıdaki yöntem imzasına sahibim:

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

AllApplesDO, ApplesDO'nun bir paketleyicisidir:

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

Jackson'ın JSON'u alt sınıflar için Java nesnelerine dönüştüremediğini düşünüyorum. Lütfen Jackson'ın JSON'u Java Nesnelerine dönüştürmesi için yapılandırma parametrelerine yardımcı olun. Spring Framework kullanıyorum.

EDIT: Yukarıdaki örnek sınıfta bu soruna neden olan büyük hata dahil - Lütfen çözüm için kabul edilen cevaba bakın.


2
Yukarıdaki kodda herhangi bir alt sınıf görmüyorum, bu kod ne deniyor veya daha basit bir örnek mi yapıyorsunuz?
gkamal

Nasıl çalıştığına dair biraz daha açıklama içeren bir cevap ekledim. Temel olarak, Java'nın yöntem bağımsız değişken adlarını çalışma zamanında tutmadığını fark etmeniz gerekir.
Vlasec

Yanıtlar:


565

Sonunda sorunun ne olduğunu anladım. Şüphe ettiğim için bu bir Jackson yapılandırma sorunu değil.

Aslında sorun ApplesDO Sınıfındaydı:

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

Sınıf için tanımlanmış özel bir kurucu vardı ve bu da onu varsayılan kurucu yaptı. Sahte bir kurucu tanıtmak hatayı ortadan kaldırdı:

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

}

CustomType'ın nereden geldiğini sorabilir miyim? Böyle bir yapı deniyorum ama Java için kesinlikle yeniyim.
andho

181
İç (iç içe) sınıflarla jackson kullanabilirsiniz, bu durumda serileştirme iyi çalışır. Tek engelleme, serileştirmenin düzgün çalışması için iç sınıfın "statik" olarak işaretlenmesi gerektiğidir. Buradaki açıklamaya bakın: cowtowncoder.com/blog/archives/2010/08/entry_411.html
jpennell

3
Birisi bunun neden olduğunu açıklayabilir mi? Çok benzer bir hatayla karşılaştım. Tüm doğru kurucuların yerinde olduğunu, ancak serileştiremediklerini düşündüm. Sadece bu yazıyı okuduktan sonra kukla bir kurucu ekledikten sonra çalıştı.
user8658912

6
@ İnsan Ben buna kukla bir kurucu demezdim - sadece varsayılan kurucu. Sadece mükemmel bir şekilde geçerli olmakla kalmaz, aynı zamanda birçok çeşit fasulye çekirdeği işleme için de gereklidir. (Ve tabii ki, beni yukarı attı. :-))
fool4jesus

2
Varsayılan yapıcı eklemek istemiyorsanız (örneğin, değiştirilemeyen nesnelerle uğraşırken). JsonCreator ek açıklamasını kullanarak nesneyi örneklemek için hangi yapıcı veya fabrika yöntemini kullanacağınızı söylemeniz gerekir.
Rahul

375

Bu şu nedenlerle olur:

  1. iç sınıfınız statik olarak tanımlanmalıdır

    private static class Condition {  //jackson specific    
    }
  2. Sınıfınızda varsayılan bir kurucunuz olmayabilir ( GÜNCELLEME: Durum böyle değil)

    private static class Condition {
        private Long id;
    
        public Condition() {
        }
    
        // Setters and Getters
    }
  3. Ayarlayıcılarınız doğru şekilde tanımlanmamış veya görünmüyor olabilir (örn. Özel ayarlayıcı)


95
statik sınıf benim durumumda fark yarattı. Teşekkürler!
jalogar

3
Ve tabii ki, sen yok , boş, hiç argüman varsayılan kurucu ilan etmeye gerek Java öyle sizin için ! (Başka kurucu tanımlamazsanız.)
Jonik

1
@Jonik, doğru! cevabım eski, doğru hatırlıyorsam, Jackson iç sınıfa ulaşmak için yansıma kullandığından, sanırım varsayılan kurucuyu tanımlamak gerekiyordu (daha yeni sürümlerde de bir durum olmayabilir), ama değilim emin olabilirsiniz.
azerafati

6
Evet, tecrübem Jackson 2.4.4 ile: gerçekten Java'nın örtük varsayılan kurucusu yeterlidir. No-args yapıcısını yalnızca argüman alan başka kurucular tanımladıysanız (yani Java sizin için argüman olmayan bir tane oluşturmazsa) açıkça yazmanız gerekir .
Jonik

2
Ayrıca benimle statik sınıf günü kurtardı.
Simon

58

Buna kukla bir kurucu gerektirmeyen başka bir çözüm eklemek istiyorum. Kukla yapıcılar biraz dağınık ve daha sonra kafa karıştırıcı olduğu için. Güvenli bir kurucu sağlayabiliriz ve kurucu argümanlarına açıklama ekleyerek jackson'ın yapıcı parametresi ile alan arasındaki eşleşmeyi belirlemesine izin veririz.

böylece aşağıdakiler de işe yarayacaktır. Ek açıklamanın içindeki dizenin alan adıyla eşleşmesi gerektiğini unutmayın.

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

}

Bu çözüm işe yaradı. Sadece aşağıdakilerden bahsetmek istiyorum, bir yapıcı vardı, ama parametrelerin adı örnek parametrelerinkinden farklıydı, bu yüzden eşleştirilemedi. Ek açıklamayı eklemek sorunu çözdü, ancak parametreleri yeniden adlandırmak da muhtemelen işe yarardı.
Fico

Yapıcı parametresi yanıtta değilse ne olur? Başka bir şekilde enjekte edilebilir mi?
Eddie Jaoude

Burada gönderiliyor yalnızca önemli veri dize elmadır olan tepkisi.
PiersyP

1
Bu benim için yararlı oldu çünkü nesnemin değişmez olmasını istedim, bu yüzden kukla bir yapıcı bir seçenek değildi.
Jonathan Pullano

Benim durumumda da @JsonCreatoryapıcı eklemek gerekir @JsonProperty.
m1ld

31

Bu sorunla karşılaştığımda, DO olarak hizmet etmek için bir iç sınıf kullanmaya çalışmanın bir sonucuydu. İç sınıfın inşası (sessizce) kapalı sınıfın bir örneğini gerektirdi - bu Jackson için mevcut değildi.

Bu durumda, iç sınıfı kendi .java dosyasına taşımak sorunu çözdü.


6
İç sınıfı kendi .java dosyasına taşımak çalışırken , statik değiştiriciyi eklemek de @ bludream'in cevabında belirtildiği gibi sorunu çözer.
jmarks

20

Genellikle bu hata varsayılan kurucu yapmadığımız için gelir, ancak benim durumumda Sorun sadece üst sınıf içinde kullanılan nesne sınıfı yapmış olmasından kaynaklanıyordu. Bu bütün günümü boşa harcadı.


Yuvalanmış sınıfı yapmak yeterlidir static.
tembellik

13

Thumb Rule : Eşleme sınıfı olarak kullandığınız her sınıf için varsayılan bir yapıcı ekleyin. Bunu kaçırdın ve sorun ortaya çıktı!
Varsayılan kurucuyu eklemeniz yeterlidir ve çalışması gerekir.


güzel cevap. teşekkür ederim. günümü kurtardım.
Steve

9

Lütfen bu yapıyı test edebilir misiniz? Eğer doğru hatırlıyorsam bu şekilde kullanabilirsiniz:

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

İkinci olarak, lütfen yardımcı olabileceği her sınıfa varsayılan kurucu ekleyin.


Çalışmıyor: Aşağıdaki hatayı alıyorum: "org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Tanınmayan alan" applesRequest "(Sınıf com.smartshop.dao.AllApplesDO), cahil olarak işaretlenmemiş"
Lucky Murari

Daha önce AllApplesDO için en azından hata yapmamaktaydı ve sadece kapalı sınıf için atıyor .. şimdi birinci sınıfın kendisi için atıyor
Lucky Murari

Varsayılan bir kurucu gerekiyordu. Teşekkürler!
Planky

bu DOĞRU cevap olarak seçilmemeli mi?
hızlı diş

7

Model sınıfımızda kukla boş yapıcı oluşturmanız gerekiyor. Bu yüzden json eşlenirken setter yöntemi ile ayarlanır.


Bu düzeltmedir.
David Kobia

Benim için de böyle. Nesnem için birçok farklı kurucum vardı ve bu yüzden görünüşe göre jackson tarafından kullanılan boş bir tane daha yarattım.
Alessandro Roaro

5

Ek açıklayıcı oluşturucuya başlarsanız, tüm alanlara ek açıklama eklemeniz gerekir.

Dikkat edin, Staff.name alanım JSON dizesinde "ANOTHER_NAME" ile eşlendi.

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

4

Jackson'ın serileştirme için hangi seçeneklerinin mevcut olduğunu anlamalısınız. Java'da, yöntem bağımsız değişken adları derlenmiş kodda bulunmaz. Bu nedenle Jackson, önceden ayarlanmış her şeyi içeren iyi tanımlanmış bir nesne oluşturmak için genellikle yapıcıları kullanamaz.

Yani, boş bir kurucu varsa ve aynı zamanda ayarlayıcılar da varsa, boş yapıcı ve ayarlayıcıları kullanır. Ayarlayıcı yoksa, bunu yapmak için biraz karanlık büyü (yansımalar) kullanılır.

Jackson ile bir kurucu kullanmak istiyorsanız, cevabında @PiersyP tarafından belirtildiği gibi ek açıklamaları kullanmalısınız. Bir oluşturucu deseni de kullanabilirsiniz. Bazı istisnalarla karşılaşırsanız, iyi şanslar. Jackson'da hata işleme büyük zaman alır, hata mesajlarındaki anlamsızlığı anlamak zordur.


"Varsayılan bir bağımsız değişken oluşturucuya" gereksinim duymanızın nedeni, büyük olasılıkla Spring, nesneleri serileştirirken ve serileştirmeyi kaldırırken otomatik olarak sıralamak ve uyumsuzlaştırmak için çalışması gereken JavaBean Spesifikasyonunu izlemesidir.
atom88

Java serileştirme ve ikili akışa serileştirme, sorunun ne olduğu ile ilgili değil zaten. Bu nedenle, Jackson'ın serileştirmeyle birlikte kullanılmak üzere birden fazla desen sunması iyidir. Özellikle ortaya çıkan nesnenin değişmez olmasına izin verdiği için oluşturucu desenini seviyorum.
Vlasec

3

Son yayın ile ilgili olarak Lombok 1.18. * 'İn kullanılması sorunu yarattı.

@Data varsayılan olarak @RequiredArgsConstructor (parametrelere sahip yapıcı) içerdiğinden, çözümüm @NoArgsConstructor (parametresiz yapıcı) eklemekti.

lombok Belgeleri https://projectlombok.org/features/all

Bu sorunu çözecektir:

package example.counter;

import javax.validation.constraints.NotNull;

import lombok.Data;

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

    @NotNull
    private final Integer int2;
}

0

Özel jackson Serializers / Deserializers'ın başarısız olması da sorun olabilir. Durumunuz olmasa da, bahsetmeye değer.

Aynı istisnayla karşılaştım ve durum böyleydi.


0

Benim için bu işe yaradı, ancak kitaplıkların yükseltilmesi bu sorunun ortaya çıkmasına neden oldu. Sorun şöyle bir sınıfa sahip olmaktı:

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

Lombok kullanma:

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

Geri dönüyor

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

Sorun düzeltildi. Neden olduğundan emin değilim, ama gelecek için belgelemek istedim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.