Skip to content

Instantly share code, notes, and snippets.

@geovanisouza92
Last active January 2, 2016 15:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geovanisouza92/8325595 to your computer and use it in GitHub Desktop.
Save geovanisouza92/8325595 to your computer and use it in GitHub Desktop.
Classes que utilizei no app Android / Classes that I used in Android app: - Android Annotations 3.0; - OrmLite/Android 4.48; - Gson 2.2.4 (que reduziu pela metade o tamanho final do app, em relação ao Jackson); - Django 1.6 / Tastypie 0.11.0 (servidor); Dessa forma, consegui trazer os dados do servidor e salvar no SQLite escrevendo muito pouco (…
package ...;
import org.androidannotations.annotations.rest.Accept;
@Rest(converters = { TastypieGsonHttpMessageConverter.class })
public interface RestServiceApi {
// Optional
void setRootUrl(String rootUrl);
// Get single object
@Get("/api/v1/<resource_uri>/{id}/")
@Accept(MediaType.APPLICATION_JSON)
MyModel getMyModel(long id);
// Get collection
@Get("/api/v1/<resource_uri>/?limit=0")
@Accept(MediaType.APPLICATION_JSON)
TastypieMessage<MyModel> getAllMyModel();
}
package ...;
import java.lang.reflect.Field;
public class TastypieDeserializer<T extends BaseModel> implements JsonDeserializer<T> {
@Override
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
try {
// Get object class to deserialize and create a new instance
Class<?> klass = (Class<?>) typeOfT;
@SuppressWarnings("unchecked")
T result = (T) klass.newInstance();
// Get all fields (including super type)
for (Field field : getAllFields(null, klass)) {
// Get field information and check if it is mapped on ORM
String fieldName = field.getName();
Class<?> fieldType = field.getType();
DatabaseField databaseField = field.getAnnotation(DatabaseField.class);
if (databaseField != null) {
// Get json field name (translating was necessary)
String fieldNameJSON = FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES
.translateName(field);
JsonElement element = json.getAsJsonObject().get(fieldNameJSON);
// If the field is foreign (relationship field)
// Get the mapped object
if (databaseField.foreign()) {
// Get id (tastypie send related resource as uri, not id)
String[] parts = element.getAsString().split("/");
long foreignId = Long.parseLong(parts[parts.length - 1]);
// Query DAO to locate the object in local
// database and avoid data inconsistence
Dao<BaseModel, Long> dao = OpenHelperManager.getHelper(null,
DatabaseHelper.class).getDao(fieldType);
BaseModel local = dao.queryForId(foreignId);
// If local found, OK
if (local != null) {
// Link object to destination object
// Ever use setters and reflection, 'cause we can :)
String setMethodName = "set"
+ Character.toUpperCase(fieldName.charAt(0))
+ fieldName.substring(1);
Method setMethod = klass.getMethod(setMethodName,
new Class[] { fieldType });
setMethod.invoke(result, local);
} else {
// If DAO object not found, Log and continue
// Throw an exception here not worked for me.
Log.w(TastypieDeserializer.class.getSimpleName(), String.format(
"Local object does not exist: [type=%s id=%d]",
fieldType.getSimpleName(), foreignId));
}
// If this is a standard data type, just deserialize it
} else {
// Add data to object
// And more reflection
String setMethodName = "set" + Character.toUpperCase(fieldName.charAt(0))
+ fieldName.substring(1);
Method setMethod = klass
.getMethod(setMethodName, new Class[] { fieldType });
Object value = context.deserialize(element, fieldType);
setMethod.invoke(result, value);
}
}
}
// Object deserialized with success!
return result;
} catch (Exception e) {
// Generaly, weird data type or SQL exception
// caused by ORM changed and database not recreated, in my case
Log.e(TastypieDeserializer.class.getSimpleName(), e.getMessage(), e);
throw new JsonParseException("Deserialize error on "
+ TastypieDeserializer.class.getSimpleName(), e);
}
}
// Util for find all field (including the super type ones)
public static List<Field> getAllFields(List<Field> fields, Class<?> type) {
if (fields == null)
fields = new ArrayList<Field>();
for (Field field : type.getDeclaredFields()) {
fields.add(field);
}
if (type.getSuperclass() != null) {
fields = getAllFields(fields, type.getSuperclass());
}
return fields;
}
}
package ...;
import org.springframework.http.converter.json.GsonHttpMessageConverter;
public class TastypieGsonHttpMessageConverter extends GsonHttpMessageConverter {
static final Gson gson = new GsonBuilder()
// Register each model and a new deserializer instance
.registerTypeAdapter(MyModel.class, new TastypieDeserializer<MyModel>())
.registerTypeAdapter(AnotherModel.class, new TastypieDeserializer<AnotherModel>())
// ... and so on ...
// In my case this was necessary
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create();
public TastypieGsonHttpMessageConverter() {
super(gson);
}
}
package ...;
import java.util.List;
public class TastypieMessage<T extends BaseModel> {
public TastypieMessageMeta meta;
public List<T> objects;
public TastypieMessage() {
}
}
package ...;
public class TastypieMessageMeta {
public int limit;
public String next;
public int offset;
public String previous;
public int total_count;
public TastypieMessageMeta() {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment