2016-11-16 3 views
0

Ich versuche, mein Charakterobjekt mit dem Gebrauch von Jackson zu serialisieren. Der mapper.writeValue Methodenaufruf erfolgreich ist wie es scheint, aber wenn ich versuche, den Wert mit der Verwendung von mapper.readValue zu lesen bekomme ich folgende Fehlermeldung:Jackson kein passender Konstruktor gefunden für android.graphics.Bitmap

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of android.graphics.Bitmap: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?) 
at [Source: [email protected]; line: 1, column: 199] (through reference chain: java.lang.Object[][0]->com.myproj.character.Character["compositeClothes"]->com.myproj.character.clothing.CompositeClothing["clothes"]->java.util.ArrayList[0]->com.myproj.character.clothing.concrete.Hat["bitmap"]) 

Das sind meine Klassen:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") 
@JsonSubTypes({ 
     @JsonSubTypes.Type(value = Hat.class, name = "hat"), 
     @JsonSubTypes.Type(value = Necklace.class, name = "necklace"), 
     @JsonSubTypes.Type(value = Shirt.class, name = "shirt") 
}) 
public interface Clothing { 
    int getCoolness(); 

    int getrId(); 

    Bitmap getBitmap(); 
} 

Mein Hut Klasse:

public class Hat implements Clothing { 
    private int rId; 
    private int coolness; 
    private Bitmap bitmap; 

    @JsonCreator 
    public Hat(@JsonProperty("coolness") int coolness, @JsonProperty("bitmap") Bitmap bitmap) { 
     rId = R.id.hat_image; 
     this.coolness = coolness; 
     this.bitmap = bitmap; 
    } 

    public int getrId() { 
     return rId; 
    } 

    @Override 
    public int getCoolness() { 
     return coolness; 
    } 

    public Bitmap getBitmap() { 
     return bitmap; 
    } 
} 

Meine Verbund Kleidung Klasse:

public class CompositeClothing implements Clothing, Iterable<Clothing> { 
    @JsonProperty("coolness") 
    private int coolness = 0; 
    private List<Clothing> clothes = new ArrayList<>(); 

    public void add(Clothing clothing) { 
     clothes.add(clothing); 
    } 

    public void remove(Clothing clothing) { 
     clothes.remove(clothing); 
    } 

    public Clothing getChild(int index) { 
     if (index >= 0 && index < clothes.size()) { 
      return clothes.get(index); 
     } else { 
      return null; 
     } 
    } 

    @Override 
    public Iterator<Clothing> iterator() { 
     return clothes.iterator(); 
    } 

    @Override 
    public int getCoolness() { 
     return coolness; 
    } 

    @Override 
    public int getrId() { 
     return 0; 
    } 

    @Override 
    public Bitmap getBitmap() { 
     return null; 
    } 
} 

Und meine Charakterklasse:

public class Character implements Observable { 
    private static final transient Character instance = new Character(); 

    @JsonProperty("compositeClothes") 
    private CompositeClothing clothes = new CompositeClothing(); 
    @JsonProperty("compositeHeadFeatures") 
    private CompositeHeadFeature headFeatures = new CompositeHeadFeature(); 

    private transient List<Observer> observers = new ArrayList<>(); 

    @JsonProperty("skin") 
    private Skin skin; 

    public void attach(Observer observer) { 
     observers.add(observer); 
    } 

    public void notifyAllObservers() { 
     for (Observer observer : observers) { 
      observer.update(); 
     } 
    } 

    public void setSkin(Skin skin) { 
     this.skin = skin; 
     notifyAllObservers(); 
    } 

    public Skin.Color getSkinColor() { 
     return skin.getColor(); 
    } 

    public Bitmap getSkinBitmap() { 
     return skin.getBitmap(); 
    } 

    public boolean hasSkin() { 
     return skin != null; 
    } 

    public void addClothing(Clothing clothing) { 
     Clothing oldClothing = (Clothing) getSameTypeObjectAlreadyWorn(clothing); 

     if (oldClothing != null) { 
      clothes.remove(oldClothing); 
     } 

     clothes.add(clothing); 
     notifyAllObservers(); 
    } 

    public CompositeClothing getClothes() { 
     return clothes; 
    } 

    private Object getSameTypeObjectAlreadyWorn(Object newClothing) { 
     Class<?> newClass = newClothing.getClass(); 

     for (Object clothing : clothes) { 
      if (clothing.getClass().equals(newClass)) { 
       return clothing; 
      } 
     } 

     return null; 
    } 

    public void removeClothing(Clothing clothing) { 
     clothes.remove(clothing); 
    } 

    public void addHeadFeature(HeadFeature headFeature) { 
     HeadFeature oldHeadFeature = (HeadFeature) getSameTypeObjectAlreadyWorn(headFeature); 

     if (oldHeadFeature != null) { 
      headFeatures.remove(oldHeadFeature); 
     } 

     headFeatures.add(headFeature); 
     notifyAllObservers(); 
    } 

    public void removeHeadFeature(HeadFeature headFeature) { 
     headFeatures.remove(headFeature); 
    } 

    public CompositeHeadFeature getHeadFeatures() { 
     return headFeatures; 
    } 

    public static Character getInstance() { 
     return instance; 
    } 
} 

Der Code, den ich verwende die Daten bestehen bleiben und dann lesen:

File charactersFile = new File(getFilesDir() + File.separator + "characters.ser"); 
ObjectMapper mapper = new ObjectMapper() 
     .setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE) 
     .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); 

try (FileWriter fileOut = new FileWriter(charactersFile, false)) { 
    List<Character> characters = Arrays.asList(character); 
    mapper.writeValue(fileOut, characters); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

Character[] characters = null; 
try (FileReader fileIn = new FileReader(charactersFile)) { 
    characters = mapper.readValue(fileIn, Character[].class); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

Dank!

+1

Putting a ' Bitmap' in JSON würde das Konvertieren in ein Textformat (z. B. base64) erfordern. Ich würde empfehlen, etwas anderes zu tun, anstatt zu versuchen, die Bitmap in den JSON zu legen. Woher kommen diese Bitmaps? – CommonsWare

+0

von den Assets, die ich mit meiner App versenden. vielleicht könnte ich meine Bitmap in ein Byte [] konvertieren, oder einfach einen Pfad verwenden? Die Sache ist, neue "Kleidung" wird der Anwendung später durch den Benutzer hinzugefügt werden und diese werden im internen Speicher gespeichert werden, die würde es etwas schwieriger finden, ich denke. – masm64

Antwort

0

Wenn Ihre Bitmaps aus Assets oder Ressourcen stammen, ist es nicht sinnvoll, die Bitmaps in JSON zu speichern. Das wäre eine Verschwendung von CPU-Zeit und Speicherplatz. Speichern Sie stattdessen einen Wert im JSON, mit dem Sie das anzuzeigende Asset oder die Ressource identifizieren können. Bedenken Sie jedoch, dass die Ressourcen-IDs (z. B. R.drawable.foo) zwischen den App-Versionen variieren können, sodass sie keine gute dauerhafte Kennung für das Bild darstellen.

+0

Ich denke, ich muss den getAssetManager() + "clothing/..." Pfad oder den getInternalStorage() + "clothing/..." Pfad zum entsprechenden Objekt speichern/hinzufügen. – masm64

0

Ich habe ähnliche Anforderungen in meiner App, wo ich zeichnbare Daten in JSON speichern muss. Ich habe es gelöst, indem ich nur seinen String-Namen gespeichert habe. Zum Beispiel, wenn ich Ressource R.drawable.testBmp dann speichere ich es in JSON wie:

{ 
    ... 
    "mydrawable" : "testBmp" 
} 

zur Laufzeit Dann werde ich es lesen und konvertieren ist als ziehbar wie folgender Code:

JSONObject jsonObj; 
... 
String bmpName = jsonObj.getString("mydrawable");   
int resId = context.getResources().getIdentifier(bmpName, 
            "drawable", 
            context.getPackageName()); 
Drawable bmp = ContextCompat.getDrawable(context,resId); 
Verwandte Themen