RoboSpice使用OrmLite保留JSON数组

我正在使用RoboSpice和Spring for Android,并希望使用OrmLite来保存JSON对象数组。 GSON用于JSON编组。 使用默认缓存,一切都按预期工作。 但OrmLite似乎不喜欢对象数组。

这是JSON的简化版本:

[{"id": 1, "title": "Test 1"},{"id": 2, "title": "Test 3"},{"id": 3, "title": "Test 3"}] 

我想在以下对象中坚持这个:

 @DatabaseTable public class Foo { @DatabaseField(id = true) private int id; @DatabaseField private String title; // getters and setters ... } 

基于RoboSpice OrmLite示例,我创建了以下GsonSpringAndroidSpiceService类来添加OrmLite CacheManager。 这是问题开始的地方。

 public class CustomGsonSpringAndroidSpiceService extends GsonSpringAndroidSpiceService { @Override public CacheManager createCacheManager(Application application) { // add persisted classes to class collection List<Class> classCollection = new ArrayList<Class>(); classCollection.add(Foo.class); // init CacheManager cacheManager = new CacheManager(); cacheManager.addPersister(new InDatabaseObjectPersisterFactory( application, new RoboSpiceDatabaseHelper( application, "database.db", 1), classCollection)); return cacheManager; } } 

这会导致以下错误:

 RequestProcessor.java:174(22356): java.lang.RuntimeException: Class [Lcom.example.model.Foo; is not handled by any registered factoryList 

当我改变classCollection.add(Foo.class); to classCollection.add(Foo[].class); 我收到以下错误:

 RequestProcessor.java:174(22601): 14:42:23.112 pool-5-thread-1 An unexpected error occured when processsing request CachedSpiceRequest [requestCacheKey=foo, cacheDuration=-1, spiceRequest=com.example.app.FooRequest@4055df40] RequestProcessor.java:174(22601): java.lang.IllegalArgumentException: No fields have a DatabaseField annotation in class [Lcom.example.app.model.Foo; 

任何人都知道如何使用OrmLite CacheManager处理JSON数组?

我找到了解决这个问题的方法。 我添加了一个额外的结果对象,它保存了对象数组。 当然,这只有在你能够操纵JSON时才有可能。 仍然不是很满意,因为我已经为我的模型引入了一个无用的类。

所以我的JSON看起来像:

 { "id": 1, "result":[{"id": 1, "title": "Test 1"},{"id": 2, "title": "Test 3"},{"id": 3, "title": "Test 3"}] } 

我添加了以下类来保存JSON结果:

 @DatabaseTable public class FooResult { @DatabaseField(id = true) private int id; @ForeignCollectionField(eager = false) private Collection result; // getters and setters ... } 

还添加了Foo类的外来关系:

 @DatabaseTable public class Foo { @DatabaseField(id = true) private int id; @DatabaseField private String title; @DatabaseField(foreign = true) private FooResult result; // getters and setters ... } 

我找到了适合我的方式。 我没有改变我的json。

 @DatabaseTable(tableName = SampleContract.Contributor.TABLE) public class Contributor { @DatabaseField(generatedId = true, columnName = SampleContract.Contributor._ID) private int id; @DatabaseField(columnName = SampleContract.Contributor.LOGIN) public String login; @DatabaseField(columnName = SampleContract.Contributor.CONTRIBUTIONS) public int contributions; @DatabaseField(foreign = true) private ContributorsResult result; @SuppressWarnings("serial") @DatabaseTable(tableName = "contributor_list") public static class ContributorsResult extends ArrayList { @DatabaseField(id = true) private int id = 0; @ForeignCollectionField(eager = false) private Collection result = this; public Collection getResult() { return result; } public void setResult(Collection result) { if (result != null) { this.clear(); this.addAll(result); } } } } 

我整个今天都在努力解决这个问题,最后想出了如何使用Robospice Spring Android将JSON数组保存到SQLite数据库中,而无需修改JSON。

这是我从服务器返回的postJSON数组:

 [ { "id": "5573547af58cd75df03306cc", "name": "Simon", "postheader": "First Post" }, { "id": "55735475f58cd75df03306cb", "name": "Tyron", "postheader": "Second Post" } ] 

这与此问题中的JSON类似:

 [{"id": 1, "title": "Test 1"},{"id": 2, "title": "Test 3"},{"id": 3, "title": "Test 3"}] 

步骤1:

你需要在android端创建2个类。

一个是您要从数组中保存的普通对象。 在我的情况下,我有一个名为“Post”的对象,我的服务器返回一个“Post”数组。

 @DatabaseTable(tableName = "post") @JsonIgnoreProperties(ignoreUnknown = true) public class Post implements Serializable { @DatabaseField(id = true) private String id; @DatabaseField private String name; @DatabaseField private String postheader; @DatabaseField(foreign = true,foreignAutoCreate = true,foreignAutoRefresh = true) private EmbedPost posts; 

另一个对象将是一个包装数组的包装器对象,我称之为“EmbedPost”。

 @DatabaseTable public class EmbedPost implements Serializable { @DatabaseField(allowGeneratedIdInsert=true, generatedId=true) private int ID; @ForeignCollectionField(eager = false) private Collection posts; 

通过在我的EmbedPost类中定义一个名为ID的int,我实际上创建了一个对象,如果我转换为JSON,它将如下所示:

 {"id": 1, "posts": [ { "id": "5573547af58cd75df03306cc", "name": "Simon", "postheader": "First Post" }, { "id": "55735475f58cd75df03306cb", "name": "Tyron", "postheader": "Second Post" } ]} 

这实际上是一个JSON字符串,看起来非常类似于Uipko在其解决方案中使用的字符串。

 { "id": 1, "result":[{"id": 1, "title": "Test 1"},{"id": 2, "title": "Test 3"},{"id": 3, "title": "Test 3"}] } 

第2步:

您现在使用SpringAndroidSpiceService继续它。

 public class AndroidSpiceService extends SpringAndroidSpiceService { private static final int WEBSERVICES_TIMEOUT = 10000; @Override public CacheManager createCacheManager( Application application ) { CacheManager cacheManager = new CacheManager(); List< Class< ? >> classCollection = new ArrayList< Class< ? >>(); // add persisted classes to class collection classCollection.add(EmbedPost.class); classCollection.add( Post.class ); // init RoboSpiceDatabaseHelper databaseHelper = new RoboSpiceDatabaseHelper( application, "sample_database.db", 3); InDatabaseObjectPersisterFactory inDatabaseObjectPersisterFactory = new InDatabaseObjectPersisterFactory( application, databaseHelper, classCollection ); cacheManager.addPersister( inDatabaseObjectPersisterFactory ); return cacheManager; } @Override public RestTemplate createRestTemplate() { RestTemplate restTemplate = new RestTemplate(); // set timeout for requests HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); httpRequestFactory.setReadTimeout( WEBSERVICES_TIMEOUT ); httpRequestFactory.setConnectTimeout( WEBSERVICES_TIMEOUT ); restTemplate.setRequestFactory( httpRequestFactory ); MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); final List> listHttpMessageConverters = restTemplate.getMessageConverters(); listHttpMessageConverters.add( mappingJackson2HttpMessageConverter ); restTemplate.setMessageConverters( listHttpMessageConverters ); return restTemplate; } } 

一定要将EmbedPost.class和Post.class都添加到classCollection中,因为如果没有两者都持久化,ORMLite就无法完成它的工作。 在编写对象时使用了ForeignKeys,这些外键必须绑定到某些东西,因此这两个类必须保持不变。

如果遇到麻烦,请尝试使用logcat来解决问题。 您可能必须阅读所有消息而不仅仅是错误消息。 请参阅我的post,了解如何阅读所有logcat消息:

Robospice存储对象,通过Ormlite在数据库中扩展ArrayList