我真的需要你的帮助,我正在尝试创建简单的厨房管理应用程序。我决定将AWS与DynamoDB一起使用,我坚持使用CRUD方法:添加和删除方法似乎工作正常,但我在编辑数据库记录时遇到很大问题。
日志文件中的错误消息:
"Can not deserialize instance of java.util.ArrayList out of START_OBJECT token "
这就是我的模型类的样子:
@DynamoDBTable(tableName = "product")
public class Product extends Request {
/**
* Id of kitchen content
*/
private String id;
/**
* Name of product
*/
private String name;
/**
* Calories in 100g
*/
private Integer calories;
/**
* Fat in 100g
*/
private Double fat;
/**
* Total carbo in 100g
*/
private Double carbo;
/**
* Total Protein in 100g
*/
private Double protein;
/**
* Labels of product for example gluten fee product
*/
private List<ProductKind> productKinds;
/**
* Author of content.
*/
private Author author;
/**
* Address of content image.
*/
private Media media;
private Boolean approved;
@DynamoDBHashKey(attributeName = "id")
@DynamoDBAutoGeneratedKey
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@DynamoDBAttribute(attributeName = "Name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@DynamoDBAttribute(attributeName = "Calories")
public Integer getCalories() {
return calories;
}
public void setCalories(Integer calories) {
this.calories = calories;
}
@DynamoDBAttribute(attributeName = "Fat")
public Double getFat() {
return fat;
}
public void setFat(Double fat) {
this.fat = fat;
}
@DynamoDBAttribute(attributeName = "Carbo")
public Double getCarbo() {
return carbo;
}
public void setCarbo(Double carbo) {
this.carbo = carbo;
}
@DynamoDBAttribute(attributeName = "Protein")
public Double getProtein() {
return protein;
}
public void setProtein(Double protein) {
this.protein = protein;
}
@DynamoDBTypeConverted(converter = EnumConverter.class)
@DynamoDBAttribute(attributeName = "ProductKinds")
public List<ProductKind> getProductKinds() {
return productKinds;
}
public void setProductKinds(List<ProductKind> productKinds) {
this.productKinds = productKinds;
}
@DynamoDBTypeConverted(converter = ObjectConverter.class)
@DynamoDBAttribute(attributeName = "Author")
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
@DynamoDBTypeConverted(converter = ObjectConverter.class)
@DynamoDBAttribute(attributeName = "Media")
public Media getMedia() {
return media;
}
public void setMedia(Media media) {
this.media = media;
}
@DynamoDBAttribute(attributeName = "Approved")
public Boolean getApproved() {
return approved;
}
public void setApproved(Boolean approved) {
this.approved = approved;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Product product = (Product) o;
if (name != null ? !name.equals(product.name) : product.name != null) return false;
if (calories != null ? !calories.equals(product.calories) : product.calories != null) return false;
if (fat != null ? !fat.equals(product.fat) : product.fat != null) return false;
if (carbo != null ? !carbo.equals(product.carbo) : product.carbo != null) return false;
if (protein != null ? !protein.equals(product.protein) : product.protein != null) return false;
if (productKinds != null ? !productKinds.equals(product.productKinds) : product.productKinds != null)
return false;
if (author != null ? !author.equals(product.author) : product.author != null) return false;
if (media != null ? !media.equals(product.media) : product.media != null) return false;
return approved != null ? approved.equals(product.approved) : product.approved == null;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (calories != null ? calories.hashCode() : 0);
result = 31 * result + (fat != null ? fat.hashCode() : 0);
result = 31 * result + (carbo != null ? carbo.hashCode() : 0);
result = 31 * result + (protein != null ? protein.hashCode() : 0);
result = 31 * result + (productKinds != null ? productKinds.hashCode() : 0);
result = 31 * result + (author != null ? author.hashCode() : 0);
result = 31 * result + (media != null ? media.hashCode() : 0);
result = 31 * result + (approved != null ? approved.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Product{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", calories=" + calories +
", fat=" + fat +
", carbo=" + carbo +
", protein=" + protein +
", productKinds=" + productKinds +
", author=" + author +
", media=" + media +
", approved=" + approved +
'}';
}
这就是我的服务方法的样子:
public class KitchenService {
public KitchenService(DatabaseController databaseController, LambdaLogger logger) {
this.databaseController = databaseController;
this.logger = logger;
}
private DatabaseController databaseController;
private LambdaLogger logger;
public Product addProduct(Product content) {
databaseController.saveTest(content);
logger.log("Product created");
return content;
}
public Product editProduct(Product product) {
Product databaseProduct = databaseController.get(Product.class, product.getId());
if (databaseProduct != null) {
logger.log("Database product exist: " + databaseProduct.toString());
}
if (product.getId() != null && product.getId().isEmpty()) databaseController.save(product);
databaseController.save(databaseProduct);
logger.log("Product updated");
return databaseProduct;
}
public void deleteProduct(Product product) {
Product databaseProduct = databaseController.get(Product.class, product.getId());
databaseController.deleteProductFromDB(databaseProduct);
logger.log("Item deleted");
}
当然,你需要看看dynamoDBcontroller中的save方法是什么样的:
public <T> void save(T objectToSave) {
logger.log("Saveing object " + objectToSave);
getMapper().save(objectToSave);
logger.log("Saved object " + objectToSave);
}
从DB方法获得:
public <T> T get(Class<T> objectClass, String id) {
logger.log("Getting object class " + objectClass + ", where id was " + id);
T data = getMapper().load(objectClass, id);
logger.log("Get data " + data);
if(data instanceof Product){
logger.log("Product Class found");
logger.log(data.toString());
}
return data;
}
我知道我需要转换器才能做好,所以我为复杂的对象类创建了通用转换器,为枚举创建了其他映射器:
对象:
public class ObjectConverter<T extends Object> implements DynamoDBTypeConverter<String, T> {
ObjectMapper objectMapper = new ObjectMapper();
@Override
public String convert(T object) {
try {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
throw new IllegalArgumentException("Unable to parse JSON");
}
@Override
public T unconvert(String object) {
try {
T unconvertedObject = objectMapper.readValue(object, new TypeReference<T>() {
});
return unconvertedObject;
} catch (JsonParseException e) {
e.getMessage();
} catch (JsonMappingException e) {
e.getMessage();
} catch (IOException e) {
e.printStackTrace();
}
throw new IllegalArgumentException("Unable to parse to JSON");
}
枚举:
public class EnumConverter<T extends Object> implements DynamoDBTypeConverter<String, List<T>> {
@Override
public String convert(List<T> objects) {
//Jackson object mapper
ObjectMapper objectMapper = new ObjectMapper();
try {
String objectsString = objectMapper.writeValueAsString(objects);
return objectsString;
} catch (JsonProcessingException e) {
//do something
}
return null;
}
@Override
public List<T> unconvert(String objectsString) {
ObjectMapper objectMapper = new ObjectMapper();
try {
List<T> objects = objectMapper.readValue(objectsString, new TypeReference<List<T>>() {
});
return objects;
} catch (JsonParseException e) {
//do something
} catch (JsonMappingException e) {
//do something
} catch (IOException e) {
//do something
}
return null;
}
我正在使用POSTMAN对此进行测试,这就是我发送的JSON的外观:
{"id":"3bdc1372-4f67-493e-92d7-db3b529fe3bd","name":"bąkiKacpraPoEdycji","calories":1500,"fat":400.0,"carbo":20.0,"protein":40.0,"productKinds":["MEAT"],"author":{"name":"Plejer Annołn","id":"testID2"},"media":{"name":"heheszki","url":"http://blabla.pl","mediaType":"IMAGE"},"approved":false}
更多详情:
产品[媒体];无法转换属性:com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException:Product [Media];无法转换属性