-1

Hi I'm trying to send a PUT request using Retrofit that uses $addToSet to my Mlab Server. I can do this using Postman but I'm having trouble doing it using Retrofit.

The collection looks like:

[
    {
        "_id": {
            "$oid": "5abe74bac2ef1603f4045686"
        },
        "email": "test@gmail.com",
        "completedWalks": [
            "South Leinster Way"
        ],
        "favWalks": []
    }
]

The post man request has the API key, Query, and then $addToSet is passed in the body as so. Postman Request And the response is: Postman Response

I'm trying to do it like this in android. Retrofit:

@PUT("databases/walks/collections/user")
Call<Update> addCompleted (@Query("apiKey") String apiKey,@Query("q") String Email, @Body Update Query);

My model:

public class Update {

    @SerializedName("n")
    private String n;

    public String getN() {
        return n;
    }

    public Update(String n) {
        this.n = n;
    }
}

Creating the update object:

String updateComplete = String.format("'$addToSet': {'completedWalks': '%s'}} ", TrailName);
final String query =String.format("{'email': '%s'}",email) ;

final Update queryComplete = new Update(updateComplete);

And the Request:

Call<Update> completeCall = apiService.addCompleted(mlabAPi, query, queryComplete);
completeCall.enqueue(new Callback<Update>() {
    @Override
    public void onResponse(Call<Update> call, Response<Update> response) {           
       Toast.makeText(getApplicationContext(),"Walk marked as Complete", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onFailure(Call<Update> call, Throwable t) {
        Log.e(TAG, t.getMessage());
    }
});

But this only overwrites whats in the collection and I have:

[
    {
        "_id": {
            "$oid": "5abe74bac2ef1603f4045686"
        },
        "n": "'$addToSet': {'completedWalks': 'Kerry Head Cycleway'}} "
    }
]

Does anyone know where I'm going wrong, should I not be passing $addToSet as a model because it seems to be overwriting all, how do I pass it then? Thank You.

iagreen
  • 31,470
  • 8
  • 76
  • 90
Paul
  • 33
  • 6

1 Answers1

1

@Body Update Query -- Retrofit will encode the object passed to this as JSON (assuming you are using the Gson converter, which it appears you are). That is where this "n": "'$addToSet': {'completedWalks': 'Kerry Head Cycleway'}} " is coming from. You need to structure you Java Object the same as your JSON object for gson to serialize it correctly.

I am not familiar with the mlab api, but from your postman, it looks like you want a request body something like this --

public class UpdateRequest {
    @SerializedName("$addToSet")
    Map<String, String> addToSet = new HashMap();
}   

Update your interface to send this object as the body --

@PUT("databases/walks/collections/user")
Call<Update> addCompleted (@Query("apiKey") String apiKey,@Query("q") String Email, @Body UpdateRequest Query);

And create the request body --

UpdateRequest requestBody = new UpdateRequest();
requestBody.addToSet.put("completedWalks", Trailname);

and create the call --

Call<Update> completeCall = apiService.addCompleted(mlabAPi, query, requestBody);

For further debugging, you can see what is actually being sent in your logcat by adding HttpLoggingInterceptor to your retrofit instance. See here for setup. Then you can compare what your app is sending vs postman and see where things might be going sideways.

iagreen
  • 31,470
  • 8
  • 76
  • 90