2011-12-15 2 views
19

Sto usando Jackson per deserializzare un array JSON in alcuni oggetti. Ecco la mia classe:Errore Jackson: nessun costruttore adatto

public class OfferContainer extends ActiveRecordBase{ 

    public Offer offer; 

    public OfferContainer(){} 

    public OfferContainer(Database db) { 
     super(db); 
    } 

    @Override 
    public String toString() 
    { 
     return this.getID() + offer.toString(); 
    } 

    public String getDescription() { 
     return offer.description; 
    } 

    public String getBusinessName() { 
     return offer.business.name; 
    } 



    public class Offer 
    { 
     public Category category; 
     public String description; 
     public String discount; 
     public Date expiration; 
     public Date published; 
     public String rescinded_at; 
     public String title; 
     public String hook; 
     public Date valid_from; 
     public Date valid_to; 
     public String id; 
     public Business business; 
     public Location location; 
     public String image_270x155; 

     public Offer() { 
     } 

     @Override 
     public String toString() 
     { 
      return String.format(
        "[Offer: category=%1$s, description=%2$s, discount=%3$s, expiration=%4$s, published=%5$s, rescinded_at=%6$s, title=%7$s, valid_from=%8$s, valid_to=%9$s, id=%10$s, business=%11$s, location=%12$s]", 
        category, description, discount, expiration, published, rescinded_at, title, valid_from, valid_to, id, 
        business, location); 
     } 

    } 

    public enum Category 
    { 
     Salon, Spa, Restaurant, Other 
    } 

// public class Category { 
//  public String category; 
// 
//  public String toString() { 
//   return String.format("[Category: category=%1$s]", category); 
//  } 
// } 


    public class Business 
    { 
     public String name; 
     public String phone; 
     public Address address; 

     public Business(){} 

     @Override 
     public String toString() 
     { 
      return String.format(
        "[Business: name=%1$s, phone=%2$s, address=%3$s]", 
        name, phone, address); 
     } 
    } 


    public class Address 
    { 
     public String address_1; 
     public String address_2; 
     public String city; 
     public String cross_streets; 
     public String state; 
     public String zip; 

     public Address() { 
     } 

     @Override 
     public String toString() 
     { 
      return String.format(
        "[Address: address_1=%1$s, address_2=%2$s, city=%3$s, cross_streets=%4$s, state=%5$s, zip=%6$s]", 
        address_1, address_2, city, cross_streets, state, zip); 
     } 
    } 

    public class Location { 
     public double latitude; 
     public double longitude; 

     public Location() { 
     } 

     public String toString() { 
      return String.format("[Location: longitude=%1$s, latitude=%2$s]", longitude, latitude); 
     } 

    } 

} 

E l'errore:

W/System.err(26911): org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type [simple type, class org.me.pojos.OfferContainer$Business]: can not instantiate from JSON object (need to add/enable type information?) 
W/System.err(26911): at [Source: [email protected]; line: 1, column: 382] (through reference chain: org.me.pojos.OfferContainer["offer"]->org.me.pojos.Offer["business"]) 
W/System.err(26911): at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObjectUsingNonDefault(BeanDeserializer.java:740) 
W/System.err(26911): at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:683) 
W/System.err(26911): at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:580) 
W/System.err(26911): at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:299) 
W/System.err(26911): at org.codehaus.jackson.map.deser.SettableBeanProperty$FieldProperty.deserializeAndSet(SettableBeanProperty.java:579) 
W/System.err(26911): at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:635) 
W/System.err(26911): at org.codehaus.jackson.map.deser.SettableBeanProperty$InnerClassProperty.deserializeAndSet(SettableBeanProperty.java:780) 
W/System.err(26911): at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:697) 
W/System.err(26911): at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:580) 
W/System.err(26911): at org.codehaus.jackson.map.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:104) 
W/System.err(26911): at org.codehaus.jackson.map.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:18) 
W/System.err(26911): at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2723) 
W/System.err(26911): at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1854) 
W/System.err(26911): at org.me.OffersUpdater.updateOffersIfNeeded(OffersUpdater.java:107) 
W/System.err(26911): at com.activities.Main$UpdateOffersTask.doInBackground(Main.java:265) 
W/System.err(26911): at com.activities.Main$UpdateOffersTask.doInBackground(Main.java:239) 
W/System.err(26911): at android.os.AsyncTask$2.call(AsyncTask.java:185) 
W/System.err(26911): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) 
W/System.err(26911): at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
W/System.err(26911): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) 
W/System.err(26911): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) 
W/System.err(26911): at java.lang.Thread.run(Thread.java:1019) 

avevo usato GSON ma bisogno di abbandonarla a causa di problemi di prestazioni. Quando sono passato a Jackson, ho solo aggiunto costruttori di default per tutte le classi, che era probabilmente inutile perché non c'erano altri costruttori definite ...

EDIT: Oh, e il JSON si presenta così:

[ { "offer" : { "business" : { "address" : { "address_1" : "340 9th Avenue", 
       "address_2" : null, 
       "city" : "New York", 
       "cross_streets" : null, 
       "state" : "NY", 
       "zip" : "10001" 
       }, 
      "name" : "Blarney Stone", 
      "phone" : "2125024656" 
      }, 
     "category" : "Restaurant", 
     "claim_link" : "http://m.thinknear.com/offers/BLARNEY__1323954754?app_id=kz4hjo&latitude=40.75042&longitude=-73.99633", 
     "description" : "$1 off all drinks This discount was authorized by Toni Rossi. ", 
     "discount" : null, 
     "distance" : 161.40291744228713, 
     "draws" : [ "American" ], 
     "expiration" : "2011-12-15T21:59:59Z", 
     "hook" : "$1 Off Drinks", 
     "id" : "BLARNEY__1323954754", 
     "image_270x155" : "https://s3.amazonaws.com/default_images/restaurant_stock_255x170.jpg", 
     "location" : { "latitude" : "40.750444", 
      "longitude" : "-73.99824579999999" 
      }, 
     "mobile_claim_link" : "http://m.thinknear.com/offers/BLARNEY__1323954754?app_id=kz4hjo&latitude=40.75042&longitude=-73.99633", 
     "published" : "2011-12-15T13:12:37Z", 
     "rescinded_at" : null, 
     "title" : "$1 Off All Drinks", 
     "valid_from" : "2011-12-15T13:12:34Z", 
     "valid_to" : "2011-12-15T21:29:59Z" 
     } }, 
    { "offer" : { "business" : { "address" : { "address_1" : "252 W 31st St", 
       "address_2" : null, 
       "city" : "New York", 
       "cross_streets" : null, 
       "state" : "NY", 
       "zip" : "10019" 
       }, 
      "name" : "Hush Spa for Men", 
      "phone" : "2127570508" 
      }, 
     "category" : "Spa", 
     "claim_link" : "http://m.thinknear.com/offers/HUSH_SPA_1323962075?app_id=kz4hjo&latitude=40.75042&longitude=-73.99633", 
     "description" : "Use this offer now to enjoy this great Spa at a 30% discount. Applies to all services except massages. This discount was authorized by Andy Paningua. ", 
     "discount" : "30", 
     "distance" : 185.37847063528784, 
     "draws" : [ "Body Work", 
      "Facial", 
      "Hair Removal" 
      ], 
     "expiration" : "2011-12-16T02:59:59Z", 
     "hook" : "30% OFF", 
     "id" : "HUSH_SPA_1323962075", 
     "image_270x155" : "https://s3.amazonaws.com/ThinkNearMobileImages/hush_255x170.jpg", 
     "location" : { "latitude" : "40.7499612", 
      "longitude" : "-73.9942143" 
      }, 
     "mobile_claim_link" : "http://m.thinknear.com/offers/HUSH_SPA_1323962075?app_id=kz4hjo&latitude=40.75042&longitude=-73.99633", 
     "published" : "2011-12-15T15:14:36Z", 
     "rescinded_at" : null, 
     "title" : "30% off at Hush Spa for Men", 
     "valid_from" : "2011-12-15T15:14:35Z", 
     "valid_to" : "2011-12-16T02:29:59Z" 
     } }, 
    { "offer" : { "business" : { "address" : { "address_1" : "481 8th Ave", 
       "address_2" : "Ste 740 ", 
       "city" : "New York", 
       "cross_streets" : "34th & 35th (New Yorker Hotel)", 
       "state" : "NY", 
       "zip" : "10001" 
       }, 
      "name" : "Fusion Spa", 
      "phone" : "+18325329272" 
      }, 
     "category" : "Spa", 
     "claim_link" : "http://m.thinknear.com/offers/FUSION_S_1323979416?app_id=kz4hjo&latitude=40.75042&longitude=-73.99633", 
     "description" : "Use this offer now to enjoy this great Spa at a 20% discount. New customers only. Not valid with other offers. By appointment only. Call ahead for appointment. This discount was authorized by Tiffany Albert. ", 
     "discount" : "20", 
     "distance" : 350.0873566571568, 
     "draws" : [ "Facial" ], 
     "expiration" : "2011-12-16T01:59:59Z", 
     "hook" : "20% OFF", 
     "id" : "FUSION_S_1323979416", 
     "image_270x155" : "https://s3.amazonaws.com/ThinkNearMobileImages/Fusion%2BSpa+1.jpg", 
     "location" : { "latitude" : "40.7526135", 
      "longitude" : "-73.99334859999999" 
      }, 
     "mobile_claim_link" : "http://m.thinknear.com/offers/FUSION_S_1323979416?app_id=kz4hjo&latitude=40.75042&longitude=-73.99633", 
     "published" : "2011-12-15T20:03:38Z", 
     "rescinded_at" : null, 
     "title" : "20% off at Fusion Spa", 
     "valid_from" : "2011-12-15T20:03:36Z", 
     "valid_to" : "2011-12-16T01:29:59Z" 
     } } 
] 
+1

Altri hanno correttamente sottolineato che le classi interne non statiche sono problematiche. Tuttavia, Jackson 1.9.0 in realtà ha qualche supporto per tali classi - quindi se si stesse utilizzando una versione precedente, l'aggiornamento potrebbe aver risolto anche le cose. Tuttavia, è buona norma usare solo le classi interne statiche se possibile (per evitare di sovraccaricare il passaggio del riferimento genitore implicito in giro) – StaxMan

risposta

64

Non ho lavorato con Jackson ma sto indovinando il problema è che la classe Business è una classe membro e non statica.

Cosa Jackson avrebbe bisogno di fare è

new OfferContainer.Business() 

Non può farlo perché è una classe membro. Prova a rendere statica la classe.

public static class Business{ 
     .... 
} 
+1

Nota che dovevo rendere statica ogni classe interna. – LuxuryMode

+2

Grazie grazie grazie mille per questa risposta! – Cuga

+0

Volevo solo dire che avevo questo errore esatto e questa era la causa. Rendere statico la classe interna ha risolto il problema. Sì, SO! – shoover

4

ho voluto accettare una risposta che qualcuno ha postato prima perché mi ha portato nella giusta direzione. Ho reso statica ogni classe membro (e successivamente ho dovuto aggiungere @JsonIgnoreProperties (ignoreUnknown = true) a uno di essi) e funziona.

+0

contento di vedere che hai funzionato. Ho iniziato ad andare nella fonte e non ho trovato nulla di ovvio –