RoboSpice使用OrmLite保留JSON数组

时间:2013-04-05 13:36:54

标签: java json spring ormlite robospice

我正在使用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);更改为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数组?

3 个答案:

答案 0 :(得分:6)

我找到了解决这个问题的方法。我添加了一个额外的结果对象,它保存了对象数组。当然,只有在你能够操纵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<Foo> 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
    ...
}

答案 1 :(得分:3)

我找到了适合我的方式。我没有改变我的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<Contributor> {

        @DatabaseField(id = true)
        private int id = 0;


        @ForeignCollectionField(eager = false)
        private Collection<Contributor> result = this;

        public Collection<Contributor> getResult() {
            return result;
        }

        public void setResult(Collection<Contributor> result) {
            if (result != null) {
                this.clear();
                this.addAll(result);
            }
        }

    }


}

答案 2 :(得分:0)

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

这是我从服务器返回的帖子JSON数组:

[
{
"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个类。

一个是您要从数组中保存的普通对象。就我而言,我有一个名为&#34; Post&#34;我的服务器返回一个&#34; Post&#34;。

的数组
@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;

另一个对象将是一个包装数组的包装器对象,我称之为&#34; EmbedPost&#34;。

@DatabaseTable
public class EmbedPost implements Serializable {
    @DatabaseField(allowGeneratedIdInsert=true, generatedId=true)
    private int ID;
    @ForeignCollectionField(eager = false)
    private Collection<Post> 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<HttpMessageConverter< ? >> listHttpMessageConverters = restTemplate.getMessageConverters();

        listHttpMessageConverters.add( mappingJackson2HttpMessageConverter  );
        restTemplate.setMessageConverters( listHttpMessageConverters );
        return restTemplate;
    }

}

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

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

Robospice storing object that extends ArrayList in database via Ormlite