JSON responses in Rails - ruby-on-rails

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 "

Related

Rails - Rack how to TEST "invalid byte sequence in UTF-8" by sending in json

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.

Rails receive params as string

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])

fluentd in http input json parser how to send multiple data in one point?

according to json parser docs https://docs.fluentd.org/v0.12/articles/parser_json
The json parser plugin parses json logs. One JSON map, par line.
when sending one json at a time everything working fine:
$.post('<server_ip>/log',
{json:JSON.stringify({
"name":"test",
})});
(i am using in_http source)
but when trying to send it a multipile points at once it always fail with
400 Bad Request 757: unexpected token
$.post('<server_ip>/log',
{
json: JSON.stringify({
"name": "test",
}) + "\n" + JSON.stringify({
"name": "test2",
})
});
edit:
the solution is:
$.post('<server_ip>/log','json=[{"name":"test"},{"name":"test2"}]');
Use batch mode with default format: https://docs.fluentd.org/v0.12/articles/in_http#batch-mode

Parsing Invalid JSON

because hardware limitation I need to parse invalid JSON formats. With NSJSONSerialization if the JSON is invalid or if have some special characters returns nil. For example
{
"/http/header":"
{\"code\":\"200\",
\"response\":\"The request has succeeded\",
\"body\":\H4؊捵ե7Ǫ㖮OƋ\"V鈭핬Ͱ枥ù޷+=豞EA㯕頎̵4kև΃
ΆץmZ-\"뺷뀕ԍ볰孖擽o<ҲA혃褿Уҥx蒊㟩g=Ң흨׮4YhkeȤ̪⤍βQ
䷹!긗Â㍡Զ䧡|jŔ䴕uA蝓蒎▖嗷н骭--̫Tʴͽ"}
}
This is a wrong JSON format but if we correct the format of this JSON the problem persists because we have special characters.
Gson on JAVA with this kind of JSON code don't have any problem, I can get the code and response value the only nil value is the body. There are someway to have the values?
Is it possible for you to correct the json format? Because the json values must not contain line breaks.
The valid json should look like this:
{
"/http/header":{
"code":"200",
"response":"The request has succeeded",
"body":"H4؊捵ե7Ǫ㖮OƋ\"V鈭핬Ͱ枥ù޷+=豞EA㯕頎̵4kև΃ΆץmZ-\"뺷뀕ԍ볰孖擽o<ҲA혃褿Уҥx蒊㟩g=Ң흨׮4YhkeȤ̪⤍βQ䷹!긗Â㍡Զ䧡|jŔ䴕uA蝓蒎▖嗷н骭--̫Tʴͽ"
}
}
So you can replace all line breaks and unnecessary backslashes
To check your JSON valid or invalid use : http://pro.jsonlint.com/
{
"/http/header": {
"code": "200",
"response": "The request has succeeded",
"body": "H4؊捵ե7Ǫ㖮OƋ\"V鈭핬Ͱ枥ù޷+=豞EA㯕頎̵4kև΃ΆץmZ-\"뺷뀕ԍ볰孖擽o<ҲA혃褿Уҥx蒊㟩g=Ң흨׮4YhkeȤ̪⤍βQ䷹!긗Â㍡Զ䧡|jŔ䴕uA蝓蒎▖嗷н骭--̫Tʴͽ"
}
}

Rails: Pretty print JSON without overkill

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."
}
}

Resources