JSON causing unprocessable entity when submitting to Rails (Error 422) - android

I'm using an android app to submit to a Rails app with a Mongo backend hosted on Heroku. I am able to use the form online to submit a new item into the mongo database, but when I try to submit JSON from an android app I get:
{"error":"Unprocessable Entity","status":"422"}
I think this may have to do with the order of JSON when I submit as it seems to have gotten mixed up in order which I realized is normal according to a past SO question. But, the solution on that question did not work for me.
Here is the construction of the JSONObject in my Android app:
JSONObject jsonObject = new JSONObject();
jsonObject.put("ph", 2);
jsonObject.put("chlorine", 2.0);
jsonObject.put("magnified_Link", url);//URLEncoder.encode(encodedImage, "UTF-8"));
jsonObject.put("taste", "yucky");
jsonObject.put("odor", "smelly");
jsonObject.put("temperature", "77.0");
jsonObject.put("mercury", 234);
jsonObject.put("hardness", 9.0);
jsonObject.put("lat", latitude);
jsonObject.put("long", longitude);
String json = jsonObject.toString(); // Output to string
Log.d(TAG, json);
StringEntity se = new StringEntity(json);
// put json string into server
httpPost.setEntity(se);
//httpPost.setHeader("Authorization", "Client-ID " +API_KEY);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
This is how the JSON appears in my android app when I log it before submission:
{"chlorine":2,"odor":"smelly","magnified_Link":"http:\/\/i.imgur.com\/JnbuUwy.jpg","long":0,"hardness":9,"ph":2,"taste":"yucky","lat":0,"mercury":234,"temperature":"77.0"}
This is how my JSON page looks like on my rails app with one successful submission into it through the online rails app:
[{"id":{"$oid":"558766f26633380003000000"},"ph":1.0,"chlorine":2.0,"magnified_Link":"3","taste":"4","odor":"5","temperature":6.0,"mercury":7.0,"hardness":8.0,"lat":40.7127,"long":-74.0059,"url":"https://distributed-health.herokuapp.com/distributed_healths/558766f26633380003000000.json"}]
Finally here is the model for a "DistributedHealth" (my object) in my rails app:
class DistributedHealth
include Mongoid::Document
field :ph, type: Float
field :chlorine, type: Float
field :magnified_Link, type: String
field :taste, type: String
field :odor, type: String
field :temperature, type: Float
field :mercury, type: Float
field :hardness, type: Float
field :lat, type: Float
field :long, type: Float
end
I can include any other relevant code and will make edits to this post as I continue trying to solve this issue.
Thank you,
Clayton.
EDIT: I have the error message from my heroku server
2015-06-23T21:29:34.382730+00:00 heroku[router]: at=info method=POST path="/distributed_healths.json" host=distributed-health.herokuapp.com request_id=2dcde4a4-3dcc-4381-98ba-6ca399400a6d fwd="128.54.58.245" dyno=web.1 connect=3ms service=14ms status=422 bytes=328

The issue ended up being a Rails side one and didn't have to do with the order of the JSON being submitted. I turned out the need for a CSRF token using the line right after class DistributedHealthsController < ApplicationController in my Controller:
skip_before_action :verify_authenticity_token
This isn't recommended as it is a work around security, but if you want to exclude certain methods this post will show you how.
More discussion on the topic can be found here and some documentation on the topic can be found here.
Even though I am now able to do a POST to my rails app I am still getting a Error 500 in my Android Studio log that looks like this:
{"error":"Internal Server Error","status":"500"}
It doesn't seem to be hindering functionality right now so I am not going to lose any sleep over it.

Related

Azure ADAL:2.0.1-alpha:Id token expiry time is always set as default

There is mismatch between the web response received by library and response expected by library.On executing acquireToken() following web response is received by library
{"not_before":"****", "token_type":"Bearer", "id_token":"****", "id_token_expires_in":"****", "profile_info":"****", "refresh_token":"****", "refresh_token_expires_in":"*****" }
While parsing the response ADAL looks for key 'idtoken_expires_in'
if(mRequest.isIdTokenRequest()){
expiresInLookUp = "idtoken_expires_in";
token = response.get(AuthenticationConstants.OAuth2.ID_TOKEN);
}
String expires_in = response.get(expiresInLookUp);
Since the web response has the key 'id_token_expires_in' and while parsing the response library is looking for "idtoken_expires_in",it is unable to find the required key and setting the token expiry time as default
This issue was fixed in 2.0.2-alpha.

Rails 4 does not receive http post content, but worked in Rails 3 [duplicate]

This question already has answers here:
XML-based RESTful API
(2 answers)
Closed 8 years ago.
I have an android application exporting data to a rails server. When I use Rails 3, everything is fine and works. But in Rails 4 the server receive instead of the content only the following parameters:
{"action"=>"export", "controller"=>"trainings"}
The content is sent by the following:
HttpPost httpPost = new HttpPost(link);
String xmlFile = createXml(locationList);
StringEntity entity = new StringEntity(xmlFile, "UTF-8");
httpPost.setEntity(entity);
httpPost.addHeader("Content-Type", "application/xml");
httpClient.execute(httpPost);
And recieved by Rails with the following code:
begin
if !params[:training].nil? && !params[:training][:location].nil? && !params[:training][:datetime].nil?
locations = params[:training][:location]
if locations.count > 0
training = Training.create! created_at: Time.at((params[:training][:datetime].to_i/1000))
locations.each do |xml_location|
if !xml_location["latitude"].nil? && !xml_location["longitude"].nil?
Location.create! latitude: xml_location["latitude"], longitude: xml_location["longitude"], training_id: training.id
end
end
end
end
rescue TimeoutError => e
end
An example for the body is the following xml:
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<training>
<datetime>1409332572032</datetime>
<location>
<longitude>-122.084095</longitude>
<latitude>37.422005</latitude>
</location>
<location>
<longitude>-122.084095</longitude>
<latitude>47.422005000000006</latitude>
</location>
<location>
<longitude>-132.08409333333333</longitude>
<latitude>47.422005000000006</latitude>
</location>
<location>
<longitude>-142.08409333333333</longitude>
<latitude>47.422005000000006</latitude>
</location>
</training>
Although I searched for changes from Rails 3 to 4, I couldn't find anything which could cause this behavior change.
One of main difference b/w rails3 and rails4 on how to handle params safely is strong_parameters. You are trying to access to params[:training] directly which is not allowed in Rails4. Here is possible solution.
add training_params function in your controller(TrainingController?):
private:
def training_params
params.require(:training).permit(:location, :datetime)
end
then use training_params instead of params. ex: training_params[:location]
Please also refer https://github.com/rails/strong_parameters for more inforamtion about strong_parameters.

How to send POST request from Android app to Rails application?

I have problem with sending POST request to my rails application from Android app (using Spring for Android)
I have following Rails controller:
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:name, :email)
end
I'm sending POST request (using Spring for Android):
RestTemplate restTemplatePost = new RestTemplate();
restTemplatePost.getMessageConverters().add(new StringHttpMessageConverter());
UserDto user = new UserDto();
user.name = "testName";
user.email = "test#fromandroid.com";
Gson gson = new Gson();
String request = gson.toJson(user);
restTemplatePost.postForObject(createUserUrl, request, String.class);
} catch(RestClientException e) {
Log.e("POST",e.getLocalizedMessage());
}
value of String request is {"email":"test#fromandroid.com","name":"testName"}
and createUserUrl has value of: http://10.0.0.2:3000/users
however, I still get the following error:
> W/RestTemplate(3299): POST request for "http://10.0.0.2:3000/users"
> resulted in 400 (Bad Request); invoking error handler
I'm able to send the GET request, but POST doesn't work. What am I doing wrong?
I used CURL to get better error message and it returns:
param not found: user
so the problem might be with required user and optional name and emails parameters which are accepted by REST API, but how should I format user in json for it to work?
I'd greatly appreciate your help!
Please ensure that your controller config accept POST method, may be it just receives GET.
RailsController
RailsRouting
And you can use RestClient (Plugin of Firefox or Chrome) to test your api.
Rest Client - Firefox
Rest Client - Chrome
There are some issues you must have to follow to post.
you need to post data something like:
{"user_params" : {"email":"test#fromandroid.com","name":"testName"}}
to create a user (according to your controller).
To post data add Request Header. As you sending json data, so header will be Content-Type: application/json.
Also I'm suggesting you to use a FireFox addons is named "RESTClient" to simulate this scenario.
Thanks.

Reading Facebook Response With Jannson JSON Reader

So long story short I have a android app and I used cocos2dx to dev it. One component I am working on is bringing my facebook friends into my game. The way I did it was on the native side (java) I setup my facebook sdk. I succefuly login and pull down my friends list without problems. My issue is that I need to forward this data to the c++ side so I can access the data and bring it into labels etc..
Here I guess some structure of how stuff is happening:
Java native - start activity, login to facebook, get friends -> STRING DATA JNI TO C++ -> CPP parse JSON data with Jannson.
My issue is that if I have a sample data like this:
[
{
"pic_square": "https://www.facebook.com/blah",
"uid": 4654546445,
"name": "somename"
}
]
I can parse that no problem, But in reality what facebook response with is something like this:
{
Response: responseCode: 200,
graphObject: GraphObject{
graphObjectClass=GraphObject,
state={
"data": [
{
"pic_square": "https://www.facebook.com/blah",
"uid": 4654546445,
"name": "somename"
}
]
}
}
}
And with that Jansson fails stating that its not an array (exact error is "error: root is not an array").
Not sure how to handle this. Should I be somehow parsing out the stuff after "data": and then figuring out where to stop correctly or is there a better way.
Thanks!!
What you'll need to do is modify the parsing logic to first handle the Json objects that wrap the data array you're interested in. Although this will require some extra programming, it definitely beats any String manipulation attempts. Unless you're a 100% sure that "[" and "]" will always be part of the response, then I wouldn't be making any assumptions about what you're receiving.
I'm not familiar with Jannson, but you'll want to do some other bits and pieces before handling the data array. Just from looking at the tutorial, it should probably look somewhat like this:
// make request
text = request(url);
// decode json
root = json_loads(text, 0, &error);
// parse "Response"
json_t *response = json_object_get(root, "Response");
json_t *responseCode = json_object_get(response, "responseCode");
int responseCodeValue = json_integer_value(responseCode);
// parse "graphObject"
json_t *graphObject = json_object_get(root, "graphObject");
json_t *graphObjectClass = json_object_get(graphObject, "graphObjectClass");
json_t *state = json_object_get(graphObject, "state");
json_t *data = json_object_get(state, "data");
// iterate over the "data" array, parse the key/values etc.
for(i = 0; i < json_array_size(data); i++) {
json_t *data = json_array_get(root, i);
}
For the sake of this example, I've omitted all type checks (you will want to add those yourself) as well as any cleaning up of memory/variables. Also, please beware of any typos and/or obvious mistakes, as I simply typed this straight into the browser and did not do any compile or runtime checks. I'm sure you'll be able to filter those out on your own.
One thing that I'm curious about is why you've opted for Jannson? I'm guessing because of its support for both Android and iOS? If you're specifically targeting Android, there are lots of other options out there. For example, basic Json support is built into the Android framework, but there's also 3rd party libraries that will enable mapping of Json to Java objects, like GSON and Jackson.

Propper way to handle dumping and reloading of JSON data containing special characters on android?

Not sure if this has been answered already but a quick search didn't turn up a satisfying result..
I'm stuck with the following scenario:
web service with REST API and JSON formatted data blobs
android client app talking to this service and locally caching / processing the data
The we service is run by a German company so some of the strings in the result data contain special characters like German umlauts:
// example resonse
[
{
"title" : "reward 1",
"description" : "Ein gro\u00dfer Kaffee f\u00fcr dich!"
},
{
"title" : "reward 2",
"description" : "Eine Pizza f\u00fcr dich!"
},
...
]
Locally the app is parsing the data using a set of classes which mirror the response objects (e.g. Reward and RewardResponse classes for the upper example). Each of these classes can read and dump itself from / to JSON - however this is where things get ugly.
Taking the example above org.json will correctly parse the data and the resulting strings will contain proper Unicode versions of the special characters 'ß' (\u00df) and 'ü' (\u00fc).
final RewardResponse response = new RewardResponse(jsonData);
final Reward reward = response.get(0);
// this will print "Ein großer Kaffee für dich!"
Log.d("dump server data", reward.getDescription());
final Reward reward2 = new Reward(reward.toJSON());
// this will print "Ein gro�er Kaffee f�r dich!"
Log.d("dump reloaded data", reward2.getDescription());
As you can see there is a problem with loading the data generated by JSONObject.toString().
Mainly whats happening is that JSONObject will parse escapes in the form of "\uXXXX" but it will dump them as plain UTF-8 text.
In turn, when parsing it won't properly read the unicode and instead insert a replacement character in the result string (� above \uffff as code point).
My current workaround consists of a look-up table containing the Unicode Latin1 supplement characters and their respective escaped versions (\u00a0 up to \u00ff). But this also means I have to go over each and every dumped JSON text and replace the characters with their escaped versions each time I dump something.
Please tell me there is a better way for this!
(Note: there is this question however he had problems with local file encoding on disk.
My problem above, as you can see, is reproducible without ever writing to disk)
EDIT: As requested in the comments here's the toJSON() method:
public final String toJSON() {
JSONObject obj = new JSONObject();
// mTitle and mDescription contain the unmodified
// strings received from parsing.
obj.put("title", mTitle);
obj.put("description", mDescription);
return obj.toString();
}
As a side note it makes no difference if I use JSONObject.toString() or a JSONStringer.
(The documentation advises to use .toString())
EDIT: just to remove Reward from the equation, this reproduces the problem:
final JSONObject inputData = new JSONObject("{\"description\":\"Ein gro\\u00dfer Kaffee\"}");
final JSONObject parsedData = new JSONObject(inputData.toString());
Log.d("inputData", inputData.getString("description"));
Log.d("parsedData", parsedData.getString("description"));
[Note: posted as an answer for better formatting]
I just tried the example
final JSONObject inputData = new JSONObject("{\"description\":\"Ein gro\\u00dfer Kaffee\"}");
final JSONObject parsedData = new JSONObject(inputData.toString());
Log.d("inputData", inputData.getString("description"));
Log.d("parsedData", parsedData.getString("description"));
on my Nexus 7 running Android 4.2.1, and on Nexus S running 4.1.2, and it works as intended:
D/inputData(17281): Ein großer Kaffee
D/parsedData(17281): Ein großer Kaffee
In which Android version did you see the problem?

Categories

Resources