杰克逊找不到适合于android.graphics.Bitmap的构造函数
问题描述:
我试图使用杰克逊序列化我的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();
}
谢谢!
答
如果您的位图来自资产或资源,将位图保存到JSON没有意义。这将浪费CPU时间和磁盘空间。相反,请将值存储在JSON中,以便您可以识别要显示的资产或资源。但是,请记住,资源ID(例如,R.drawable.foo
)可能因应用程序版本而异,因此这不是图像的良好持久标识符。
+0
我想我需要将getAssetManager()+“clothing/...”路径或getInternalStorage()+“clothing/...”路径存储/添加到相应的对象。 – masm64
答
我在我的应用程序中有类似的需求,我需要将可绘制数据存储在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);
把一个' JSON中的位图需要将其转换为一些文本格式(例如base64)。我会推荐做其他事情,而不是试图把位图放入JSON中。这些位图来自哪里? – CommonsWare
来自我随应用附带的资产。也许我可以将我的位图转换为一个字节[],或者只是使用路径?事情是新的,“布料”将在稍后由用户添加到应用中,并且这些将被存储在内部存储装置中,这将使得我想要定位它更难一些。 – masm64