I'm building an API with Ruby on Rails. Because of that, I can't force the params to follow sone restriction.
Currently, I'm having an error with params that contained a Windows newline, because the newline isn't escaped.
The request body looks like below:
{
"name": "Jon Do",
"address": "6th Street\r\nDistrict City\r\nNation"
}
And it generated JSON::ParserError: 784: unexpected token
How to correctly process that request so params[:address] can be called without error?
When passing the data from front-end, make it JSON.stringify, and parse from back-end.
#Front-end
address: JSON.stringify(objects)
#Back-end
JSON.parse(params[:address])
Related
I have been working on a middleware that encodes the body for UTF-8 and returns a 422 to the client if the string cannot be encoded. I have passing specs.
There are 99,234,3978,224 articles(I googled) on how to handle this but not how to test, and by test, I want to send invalid JSON to my local server via curl or postman.
I have tried a few things all POST's
{ "name": "bad string \255" }
{ "name": "bad string \xAD" }
{ "name": "bad string <invaild japanese chars that some other post said was invaild>" }
Either ad chars where escaped the \ by adding another one or just treated it like text, which makes sense but not what I want.
What has to be wrong with a contact submitted to the contacts/bulk operation (described here) for it to be put in the invalids collection shown in the response?
When I exceed the field lengths cited here, SurveyMonkey just truncates the field and returns it in the successful collection. If I put an invalid character in the email address, it just returns a 500 error.
The invalids key is for invalid emails, basically emails that don't match some email validation regex.
So if you POST something like
{
"contacts": [{
"first_name": "Test",
"last_name": "Example",
"email": "notanemail"
}]
}
That should go into the invalids list. If invalid characters are causing a 500, that's something I would report as a bug to SurveyMonkey's API support.
I am using an API for my university project, which sends me multiple responses which are all valid JSON.
Both are treated as string in response.body so I need to parse them into JSON or ruby object.
The first one passes through the JSON parser but fails if I use eval which returns a ruby object
{
apiCode: "SUCCESS",
friendlyMessage: "All information saved successfully"
}
Second one passes through eval and gives me a valid Ruby object but fails as a valid JSON.
{
apiCode: "SUCCESS_WITH_ERRORS",
friendlyMessage: "Some of the information was not processed",
successfulIds: [
{
ssid: "My Test 1",
bssid: "2d:8c:e5:5c:bb:b9"
},
{
ssid: "My Test 2",
bssid: "2a:7d:a4:5c:aa:a7"
}
]
Regards,
Babar
Running both your JSON blobs through both JSON Lint and Ruby's JSON library results in an error.
The error for the first one is
Error: Parse error on line 1:
{ apiCode: "SUCCESS",
--^
Expecting 'STRING', '}', got 'undefined'
and for the second one is
Error: Parse error on line 1:
{ apiCode: "SUCCESS_WI
--^
Expecting 'STRING', '}', got 'undefined'
The errors suggest that your JSON should look like (I'm showing the first one here)
{
"apiCode": "SUCCESS",
"friendlyMessage": "All information saved successfully"
}
(which parses successfully everywhere).
Using eval for parsing data coming from some external source is a bad idea, because opens a direct code execution vulnerability.
For parsing JSON there's a build-in parser:
require 'json'
ruby_object = JSON.load(your_json_string)
For more speed, if you need it, use a dedicated json parser gem like oj directly or through MultiJson gem.
Also your second json is missing the final } so is not valid, also hash keys in json are supposed to be in "
I'm using the below code to display an unauthorized message in JSON:
def render_unauthorized
# Displays the Unauthorized message since the user did
# not pass proper authentication parameters.
self.headers['WWW-Authenticate'] = 'Token realm="API"'
render json: {
error: {
type: "unauthorized",
message: "This page cannot be accessed without a valid API key."
}
}, status: 401
end
Which outputs:
{"error":{"type":"unauthorized","message":"This page cannot be accessed without a valid API key."}}
So my question is this: Is there a way to pretty print this message (WITHOUT putting it in a separate view and using some 3rd party gem).
Edit: What is pretty print?
Properly spaced, and well .. pretty. Here's the output I'd like to see:
{
"error": {
"type": "unauthorized",
"message": "This page cannot be accessed without a valid API key."
}
}
Solution
Using #emaillenin's answer below worked. For the record, here's what the final code looks like (since he hadn't included the whole thing):
def render_unauthorized
# Displays the Unauthorized message since the user did
# not pass proper authentication parameters.
self.headers['WWW-Authenticate'] = 'Token realm="API"'
render json: JSON.pretty_generate({ # <-- Here it is :')
error: {
type: "unauthorized",
message: "This page cannot be accessed without a valid API key."
}
}), status: 401
end
Use this helper method built into JSON.
JSON.pretty_generate
I just tried and it works:
> str = '{"error":{"type":"unauthorized","message":"This page cannot be accessed without a valid API key."}}'
> JSON.pretty_generate(JSON.parse(str))
=> "{\n \"error\": {\n \"type\": \"unauthorized\",\n \"message\": \"This page cannot be accessed without a valid API key.\"\n }\n}"
If you (like I) find that the pretty_generate option built into Ruby's JSON library is not "pretty" enough, I recommend my own NeatJSON gem for your formatting.
To use it gem install neatjson and then use JSON.neat_generate instead of JSON.pretty_generate.
Like Ruby's pp it will keep objects and arrays on one line when they fit, but wrap to multiple as needed. For example:
{
"navigation.createroute.poi":[
{"text":"Lay in a course to the Hilton","params":{"poi":"Hilton"}},
{"text":"Take me to the airport","params":{"poi":"airport"}},
{"text":"Let's go to IHOP","params":{"poi":"IHOP"}},
{"text":"Show me how to get to The Med","params":{"poi":"The Med"}},
{"text":"Create a route to Arby's","params":{"poi":"Arby's"}},
{
"text":"Go to the Hilton by the Airport",
"params":{"poi":"Hilton","location":"Airport"}
},
{
"text":"Take me to the Fry's in Fresno",
"params":{"poi":"Fry's","location":"Fresno"}
}
],
"navigation.eta":[
{"text":"When will we get there?"},
{"text":"When will I arrive?"},
{"text":"What time will I get to the destination?"},
{"text":"What time will I reach the destination?"},
{"text":"What time will it be when I arrive?"}
]
}
It also supports a variety of formatting options to further customize your output. For example, how many spaces before/after colons? Before/after commas? Inside the brackets of arrays and objects? Do you want to sort the keys of your object? Do you want the colons to all be lined up?
Using the aligned option would allow your output to look like this:
{
"error": {
"type" : "unauthorized",
"message" : "This page cannot be accessed without a valid API key."
}
}
I'm trying to use the create_flow endpoint to the Survey Monkey API. It is sending back a status 3 message with the following error:
additional properties not defined by 'properties' are not allowed in field '_data'
I'm able to do successfully use all other API endpoints and have a valid API key and durable OAuth token.
Here's an example JSON body that I'm sending to: https://api.surveymonkey.net/v2/batch/create_flow?api_key=apikeyhere
{
"survey": {
"template_id": "566",
"survey_title": "test1",
"collector": {
"type": "email",
"name": "collector1",
"recipients": [
{
"email": "email#example.com"
}
]
},
"email_message": {
"reply_email": "myemail#example.com",
"subject": "this is a test"
}
}
Note: JSON formatting here is being generated automatically using RJSONIO
Any ideas what might be causing the error? It seems like all fields are correctly named and where they're supposed to be, so I'm not sure what the problem is.
It's a bad error message unfortunately - it's a known issue. It means you are providing extra keys that are not part of the create_flow schema.
The issue here is that the "email_message" and "collector" keys have been nested inside of "survey", instead of being in the main JSON body like the "survey" key. Move them out a level and it should work.