Reputation: 94
I have recently taken over a project that uses Android's Room persistence library as well as Retrofit. Unfortunately I am not very knowledgeable in either of these libraries.
I am currently trying to send through a JSON array of records saved with Room to an API using retrofit.
My entity looks like this:
@Entity(tableName = "location_table")
public class LocationEntity implements Serializable {
@NonNull
@PrimaryKey(autoGenerate = true)
private int id;
@SerializedName("job_id")
@ColumnInfo(name = "job_id")
@Expose
private String job_id;
@SerializedName("coordinates")
@ColumnInfo(name = "coordinates")
@Expose
private String coordinates;
@SerializedName("created_at")
@ColumnInfo(name = "created_at")
@Expose
private String created_at;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getJob_id() { return job_id; }
public void setJob_id(String job_id) { this.job_id = job_id; }
public String getCoordinates() { return coordinates; }
public void setCoordinates(String coordinates) { this.coordinates = coordinates; }
public String getCreated_at() { return created_at; }
public void setCreated_at(String created_at) { this.created_at = created_at; }
@Ignore
public LocationEntity() {
// DATA TO IGNORE
}
public LocationEntity(String job_id, String coordinates, String created_at) {
this.job_id = job_id;
this.coordinates = coordinates;
this.created_at = created_at;
}
}
In my DOA I have:
@Dao
public interface LocationDAO {
@Query("SELECT * from location_table ORDER BY id ASC")
List<LocationEntity> getAll();
}
And the Repository has:
public class LocationRepository {
private static BudtrackDatabase budtrackDatabase;
public LocationRepository(Context context) {
budtrackDatabase = Room.databaseBuilder(context, BudtrackDatabase.class, AppConstants.DATABASE_NAME).build();
}
public static List<LocationEntity> getLocations() {
return budtrackDatabase.locationDAO().getAll();
}
}
My request:
public interface LocationRequest {
/**
* Send through multiple locations
* @param token
* @param coordinates
*/
@FormUrlEncoded
@POST("api/coordinates")
Call<String> sendLocations(@Field("token") String token,
@Field("coordinates[]") List<LocationEntity> coordinates);
}
I then try to send the data using retrofit like so:
String token = "12345";
List<LocationEntity> locations = locationRepository.getLocations();
Call<String> callLocation = sendLocationService.sendLocations(token, locations);
callLocation.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.isSuccessful()) {
// Logic for success
} else {
try {
JSONObject jObjError = new JSONObject(response.errorBody().string());
Toast.makeText(activity, jObjError.getString("message"), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(activity, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Log.e("Failed To Send Location", t.getMessage());
}
});
I then get the data on the API side like so:
"coordinates" : [
"com.yard8.budtrack.data.location.LocationEntity@4d87c17",
"com.yard8.budtrack.data.location.LocationEntity@6c60804",
"com.yard8.budtrack.data.location.LocationEntity@fdad1ed",
"com.yard8.budtrack.data.location.LocationEntity@66fc822",
"com.yard8.budtrack.data.location.LocationEntity@8dec2b3",
"com.yard8.budtrack.data.location.LocationEntity@f9da070",
];
What is the correct way of sending through the data so that it comes through as a JSON array?
Upvotes: 0
Views: 1301
Reputation: 94
I may have been trying to over-complicate things and all I needed to do was change
@Field("coordinates[]") List<LocationEntity> coordinates
to
@Field("coordinates") String coordinates
And then before the call use...
Gson gson = new Gson();
String locations = gson.toJson(locationRepository.getLocations());
...and pass it through as my second parameter.
Call<String> callLocation = sendLocationService.sendLocations(token, locations);
I really thought this would only work on a single object and not a list of them because of the way I had been receiving the data server side.
Upvotes: 2
Reputation: 1876
Have you try something like this
1. Creating new Class
class ParentEntity{
private List<LocationEntity> locationEntities;
public List<LocationEntity> getLocationEntities() {
return locationEntities;
}
public void setLocationEntities(List<LocationEntity> locationEntities) {
this.locationEntities = locationEntities;
}
}
2. Then in your response retrofit
// ....... //
@Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.isSuccessful()) {
// Logic for success
ParentEntity readObj = response.body();
List<LocationEntity> locations = readObj.getLocationEntities();
// DO SOMETHING YOU WANT
} else {
try {
JSONObject jObjError = new JSONObject(response.errorBody().string());
Toast.makeText(activity, jObjError.getString("message"), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(activity, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
// ....... //
UPDATE
try using @Body
, probably the structure like below
1. Create new Class
class ParentEntity{
private LocationEntity location;
private String token;
public LocationEntity getLocation() {
return location;
}
public void setLocation(LocationEntity location) {
this.location = location;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
Use Body instead of Field, also without @FormUrlEncoded
@POST("/") Call sendLocations(@Body ParentEntity parentEntity);
Upvotes: 0