How do I clean a JSON string with serialized formatting? - ruby

I tried to decode and parse the string that an API returns, however the syntax of the returned JSON object is weird.
I could just strip elements from the string, but was wondering what is the best way to clean up this JSON string and convert it to a Ruby hash?
"DataCallBack([
{
\"detail1\": \"result1\",
\"detail2\": \"result2\",
\"Attr1\": [
{
\"detail1\": \"result1\",
\"detail2\": \"result2\",
},
{...}
]
],
\"Attr2\": [
{
\"detail1\": \"result1\",
\"detail2\": \"result2\",
},
{...}
]
}
])"

Just request the data without the ?callback=DataCallBack in the query string, and you will probably get raw JSON that you can directly parse.

It's easy to strip the JSON from a JSONP response:
jsonp = 'DataCallBack([
{
"detail1": "result1",
"detail2": "result2",
"Attr1": [
{
"detail1": "result1",
"detail2": "result2"
}
],
"Attr2": [
{
"detail1": "result1",
"detail2": "result2"
}
]
}
])'
require 'json'
JSON.parse(jsonp[/{.+}/m])
# => {"detail1"=>"result1",
# "detail2"=>"result2",
# "Attr1"=>[{"detail1"=>"result1", "detail2"=>"result2"}],
# "Attr2"=>[{"detail1"=>"result1", "detail2"=>"result2"}]}
Your JSONP sample was mangled a bit, probably by trying to shorten it, so I cleaned it up to be valid JSON.
The pattern /{.+}/m tells the regular expression engine to find everything contained by the outermost curly braces, which is the JSON. The m flag tell the engine to treat the whole string, containing line-ends, as a long string, which is necessary when using . because it won't normally match line-ends. At that point you'll have the JSON content, so then it's a simple matter of parsing it back into a Ruby object.

Related

Issues getting flow to send the correct json in body when using powerautomate's http request

I'm using a PowerAutomate Flow to call a native SmartSheet API that does a POST. The POST IS working but my MULTI_PICKLIST type field is not being populated correctly in SmartSheet due to the double quotes.
The API is: concat('https://api.smartsheet.com/2.0/sheets/', variables('vSheetID'), '/rows')
In the Body section of the http rest API I form my JSON and the section of interest looks like this:
{
"columnId": 6945615984781188,
"objectValue": {
"objectType": "MULTI_PICKLIST",
"values": [
#{variables('vServices')}
]
}
}
My variable vServices raw output looks like:
{
"body":
{
"name": "vServices",
"value": "Test1, Test2"
}
}
The format needs to be like this (it works using PostMan).
{
"columnId": 6945615984781188,
"objectValue": {
"objectType": "MULTI_PICKLIST",
"values": [
"Test1","Test2"
]
}
}
As a step in formatting my vServices variable I tried to do a replace function to replace the ',' with a '","' but this ultimately ends up as a \",\"
Any suggestion on how to get around this? Again, ultimately I need the desired JSON Body to read but haven't been able to achieve this in the Body section:
{
"columnId": 6945615984781188,
"objectValue": {
"objectType": "MULTI_PICKLIST",
"values": [
"Test1","Test2"
]
}
}
vs this (when using replace function).
{
"columnId": 6945615984781188,
"objectValue": {
"objectType": "MULTI_PICKLIST",
"values": [
"Test1\",\"Test2"
]
}
}
Thank you in advance,
I resolved my issue by taking the original variable, sending it to a compose step that did a split on the separator of a comma. I then added a step to set a new variable to the output of the compose step. This left me with a perfectly setup array in the exact format I needed! This seemed to resolve any of the issues I was having with double quotes and escape sequences.

Search for array value inside JSON column

When there is a single value, whereJsonContains does the job. But in this case, I have an array which is as a result of saving to JSON column being converted into string. Here is the example:
[
{
"key":"cUyV6kW3noxxW85G",
"value":"value-1",
},
{
"key":"R8dHf4vWBS8M4W5G",
"value":"value-2",
"multidimensional_array":{
"table":[
{
"attributes":{
"array":"[\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"10\"]"
}
}
],
}
},
{
"key":"cUyV6kW3noxxW85G",
"value":"value-3",
},
]
I want to get those elements which contain specific value inside array. Here is my try, but it's not working, no results are being returned:
ExampleTable::whereJsonContains('example_column', ['multidimensional_array' => ['table' => ['attributes' => ['array' => $specific_value]]]])->get();
Is it even possible to do it this way, or do I need to get every single result which has multidimensional_array and json_decode() array so I can iterate over it to look for what I need?
take a look at the documentation: https://laravel.com/docs/master/queries#json-where-clauses
You should use the whereJsonContains a bit different;
ExampleTable::whereJsonContains('multidimensional_array->table->attributes->array', $specific_value)->get();

Ruby - Parse a file into hash

I've a file containing hundreds of object and value combination like below manner. I want to get input from user as object name & numeric value and return that associated value.
Object cefcFRUPowerOperStatus
Type PowerOperType
1:offEnvOther
2:on
3:offAdmin
4:offDenied
5:offEnvPower
6:offEnvTemp
Object cefcModuleOperStatus
Type ModuleOperType
1:unknown
2:ok
3:disabled
4:okButDiagFailed
5:boot
6:selfTest
E.g. - input -
objectName = 'cefcModuleOperStatus'
TypeNumber = '4'
Return - 'okButDiagFailed'
I am not aware of Ruby and get this done to help my peer. So please excuse if this is a novice question.
Note:- I've to create the file so with any file format it would be a great help.
If like you say you have control over creating the original data file, then creating it in json format would make accessing it trivial.
Here is a repl.it of complete working example. Just select the main.rb file and hit run!
For example if you create json file like:
data.json
{
"cefcFRUPowerOperStatus": {
"type": "PowerOperType",
"status": {
"1": "offEnvOther",
"2": "on",
"3": "offAdmin",
"4": "offDenied",
"5": "offEnvPower",
"6": "offEnvTemp"
}
},
"cefcModuleOperStatus": {
"type": "ModuleOperType",
"status": {
"1": "unknown",
"2": "ok",
"3": "disabled",
"4": "okButDiagFailed",
"5": "boot",
"6": "selfTest"
}
}
}
Then parsing it and accessing it in Ruby is as simple as :
require 'json'
file = File.read('data.json')
data = JSON.parse(file)
#accessing this data is simple now:
puts data["cefcModuleOperStatus"]["status"]["4"]
# > okButDiagFailed
Note: that this JSON format will work if your statuses are unique. If they are not, you can still use this way, but you will need to convert JSON to an array format. Let me know if this is the case and I can show you how to modify the json and ruby code for this.
Hope that helps, let me know if you have further questions about how this works.

Parsing HTTParty response

I'm using HTTParty to pull a list of a Facebook user's books but I'm having trouble parsing the response:
Facebook returns data this way:
{
"data": [
{
"name": "Title",
"category": "Book",
"id": "21192118877902",
"created_time": "2011-11-11T20:50:47+0000"
},
{
"name": "Title 2",
"category": "Book",
"id": "1886126860176",
"created_time": "2011-11-05T02:35:56+0000"
},
And HTTParty parses that into a ruby object. I've tried something like this (where ret is the response) ret.parsed_response and that returns the data array, but actually accessing the items inside returns a method not found error.
This is a sample of what HTTParty actually returns:
#<HTTParty::Response:0x7fd0d378c188 #parsed_response={"data"=>
[{"name"=>"Title", "category"=>"Book", "id"=>"21192111877902", "created_time"=>"2011-11-11T20:50:47+0000"},
{"name"=>"Title 2", "category"=>"Book", "id"=>"1886126860176", "created_time"=>"2011-11-05T02:35:56+0000"},
{"name"=>"Thought Patterns", "category"=>"Book", "id"=>"109129539157186", "created_time"=>"2011-10-27T00:00:16+0000"},
Do you have any code that is throwing an error? The parsed_response variable from the HTTParty response is a hash, not an array. It contains one key, "data" (the string, NOT the symbol). The value for the "data" key in the hash is an array of hashes, so you would iterate as such:
data = ret.parsed_response["data"]
data.each do |item|
puts item["name"]
puts item["category"]
puts item["id"]
# etc
end
Just an additional info - It's Not Always a default JSON response
HTTParty's result.response.body or result.response.parsed_response does not always have form of a Hash
It just depends generally on the headers which you are using in your request. For e.g., you need to specify Accept header with application/json value while hitting GitHub API, otherwise it simply returns as string.
Then you shall have to use JSON.parse(data) for same to convert the string response into Hash object.

Efficiently check that a JSON response contains a specific element within an array

Given the JSON response:
{
"tags": [
{
"id": 81499,
"name": "sign-in"
},
{
"id": 81500,
"name": "user"
},
{
"id": 81501,
"name": "authentication"
}
]
}
Using RSpec 2, I want to verify that this response contains the tag with the name authentication. Being a fairly new to Ruby, I figured there is a more efficient way than iterating the array and checking each value of name using include? or map/collect. I could simply user a regex to check for /authentication/i but that doesn't seem like the best approach either.
This is my spec so far:
it "allows filtering" do
response = #client.story(15404)
#response.tags.
end
So, if
t = JSON.parse '{ ... }'
Then this expression will either return nil, which is false, or it will return the thing it detected, which has a boolean evaluation of true.
t['tags'].detect { |e| e['name'] == 'authentication' }
This will raise NoMethodError if there is no tags key. I think that's handled just fine in a test, but you can arrange for that case to also show up as false (i.e., nil) with:
t['tags'].to_a.detect { |e| e['name'] == 'authentication' }

Resources