2016-11-16 71 views
0

我試圖使用傑克遜序列化我的Character對象。該mapper.writeValue方法調用成功似乎,但是當我嘗試使用mapper.readValue的閱讀價值,我得到了以下錯誤消息:傑克遜找不到適合於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"]) 

這些都是我的課:

@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(); 
} 

我的帽子類:

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

我複合服裝類:

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

而且我的性格類:

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

,我使用堅持,然後讀取數據的代碼:

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

謝謝!

+1

把一個' JSON中的位圖需要將其轉換爲一些文本格式(例如base64)。我會推薦做其他事情,而不是試圖把位圖放入JSON中。這些位圖來自哪裏? – CommonsWare

+0

來自我隨應用附帶的資產。也許我可以將我的位圖轉換爲一個字節[],或者只是使用路徑?事情是新的,「布料」將在稍後由用戶添加到應用中,並且這些將被存儲在內部存儲裝置中,這將使得我想要定位它更難一些。 – masm64

回答

0

如果您的位圖來自資產或資源,將位圖保存到JSON沒有意義。這將浪費CPU時間和磁盤空間。相反,請將值存儲在JSON中,以便您可以識別要顯示的資產或資源。但是,請記住,資源ID(例如,R.drawable.foo)可能因應用程序版本而異,因此這不是圖像的良好持久標識符。

+0

我想我需要將getAssetManager()+「clothing/...」路徑或getInternalStorage()+「clothing/...」路徑存儲/添加到相應的對象。 – masm64

0

我在我的應用程序中有類似的需求,我需要將可繪製數據存儲在JSON中。我通過只存儲它的字符串名來解決它。舉例來說,如果我有資源R.drawable.testBmp然後我把它保存在JSON,如:

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

在運行的時候,我會讀它,並轉化爲像下面的代碼繪製:

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