Подход к сериализации класса модели конечных точек облака для файловой системы Android

Я успешно создал модель конечных точек для облаков, которая позволяет легко извлекать информацию из App Engine. Чтобы уменьшить количество обращений и обеспечить более быстрый пользовательский интерфейс, я определил один экземпляр, который я хочу сохранить в локальном хранилище.

На протяжении всего моего приложения я использую ObjectInputStream для чтения и записи таких объектов, как:

FileInputStream fis = context.openFileInput("PRIVFILE"); ObjectInputStream ois = new ObjectInputStream(fis); AppModelState s = (AppModelState) ois.readObject(); 

Это, очевидно, требует, чтобы все члены данных реализовали интерфейс Serializable. Класс Model расширяет GenericJSON и не является «Serializable», так как

  public final class ModelClass extends GenericJson {} 

Я мог бы вручную создать сериализуемый объект, который сопоставляется с моделью; Однако, это кажется очень любительским из-за количества атрибутов.

Другой альтернативой, которую я рассматривал, является создание обертки Serializable Object, которая просто имеет строку JSON в качестве члена и предоставляет setter / getter, принимающий ModelClass в качестве параметров, таких как:

 class AppModelState implements Serializable { private String modelClassJSON; public ModelClass getModelClass() { // generate a new ModelClass from the JSON } public void setModelClass(ModelClass c) { // extract the JSON for storage } ..... } 

Я чувствую, что должен быть лучший способ, и это нужно было решить десяток раз, но я не нахожу никаких ресурсов. Пожалуйста, укажите ввод.

Я думаю, что выполнение стандартной сериализации Java классов, которая будет использоваться с Endpoints, работает не очень хорошо. Проблема в том, что сериализация двоичная, а HTTP comm – строка.

Если вы делали HTTP-коммит самостоятельно, а не используя конечные точки, я думаю, что у вас будет такая же проблема. Чтобы отправить объект, вы его сериализуете (преобразовывая члены строки в двоичный), а затем вам придется преобразовать двоичный код обратно в строку.

Таким образом, если количество данных, которые вы используете, не слишком много, вероятно, было бы проще хранить ваши объекты как JSON.

Я делаю то же самое, что вы говорите в своем вопросе.

Поскольку объекты Cloud Endpoints уже сериализованы для передачи по проводу, они также могут быть сериализованы для локального хранения. В качестве дополнительного бонуса, с Android 3.0 или новее, вам даже не нужно импортировать какие-либо библиотеки – это уже есть! Например:

 import com.google.api.client.extensions.android.json.AndroidJsonFactory; import com.google.api.client.json.GenericJson; import com.google.api.client.json.JsonFactory; private static final JsonFactory JSON_FACTORY = new AndroidJsonFactory(); public void putObject(String key, Object value) throws Exception { byte[] outputbytes = null; if (value instanceof GenericJson) { outputbytes = JSON_FACTORY.toByteArray(value); } else { ByteArrayOutputStream output = new ByteArrayOutputStream(); ObjectOutputStream objectstream = new ObjectOutputStream(output); objectstream.writeObject(value); objectstream.close(); outputbytes = output.toByteArray(); } // persist "outputbytes" ... } public <T> T getObject(String key, Class<T> outclass) throws Exception { // retrieve saved bytes... byte[] valuebytes = ... if (valuebytes[0] == '{' && valuebytes[1] == '"' && valuebytes[valuebytes.length-1] == '}') { // Looks like JSON... return JSON_FACTORY.fromString(new String(valuebytes, "UTF-8"), outclass); } else { ByteArrayInputStream input = new ByteArrayInputStream(valuebytes); ObjectInputStream objectstream = new ObjectInputStream(input); Object value = objectstream.readObject(); objectstream.close(); return outclass.cast(value); } } 

Обратите внимание, что по умолчанию AndroidJsonFactory (как и Android v4.3, во всяком случае) довольно медленный при сериализации длинных строк. Создайте новый JacksonFactory если у вас проблемы с производительностью. Все остальное остается прежним.

Обновление. Если вы хотите сериализовать список объектов GenericJson, вам просто нужно создать объект GenericJson, который включает в себя список этих объектов. Например:

 import com.google.api.client.json.GenericJson; import com.google.api.client.util.Key; public static class PersistantJson extends GenericJson { @Key public int one; @Key public String two; } public static class PersistantJsonList extends GenericJson { @Key public List<PersistantJson> list = new ArrayList<PersistantJson>(); } 

Теперь вы можете добавить все свои объекты .list (т.е. некоторый класс, созданный объектами «генерировать облачную конечную точку») в элемент .list переменной putObject() а затем передать эту переменную putObject() . Обратите внимание, что для этого требуется, чтобы все объекты в списке были одного класса, так что десериализация знает, что такое тип (поскольку сериализация JSON не записывает тип). Если вы используете List<Object> то прочитанное будет List<Map<String, Object>> и вам нужно извлечь поля вручную.

Это кажется открытым вопросом.

Последнее ключевое слово блокирует нас от расширения класса и делает его Serializable, чтобы мы могли обменивать объекты, возвращаемые облачными конечными точками между действиями. Таким образом, предлагаемое подклассическое решение не может работать в этом случае.

Кто-нибудь знает другое решение, пожалуйста?