If a key has a value then print the value ruby - json

I'm trying to only put value of the key self only if the key escalation_policies has a value. This is an example a schedule that doesn't have an escalation policy hence I don't want the value for the key self
{"schedules"=>
[{"id"=>"0000000",
"type"=>"schedule",
"summary"=>"-PROD-",
"self"=>"https://api.pagerduty.com/schedules/",
"html_url"=>"https://pagerduty.com/schedules/",
"name"=>"-PROD-",
"time_zone"=>"America/",
"description"=>nil,
"privilege"=>nil,
"users"=>
[{"id"=>"0000000",
"type"=>"user_reference",
"summary"=>"DOo Kkkk",
"self"=>"https://api.pagerduty.com/users/",
"html_url"=>"https://target.pagerduty.com/users/"}],
"escalation_policies"=>[],
"teams"=>[]},
}
My code to conquer this challenge is:
somefile = File.open("Schedule_Api.txt", "a+")
jdoc.fetch("schedules").each do |schedule|
somefile.puts schedule["self"] if schedule["escalation_policies"].exists? == true
end
somefile.close
This variable jdoc is the curl for the website. And this is the result I get from this is undefined methodexists?' for []:Array (NoMethodError). Is there another alternative to this then the methodexists?`. Any help will be helpful! Thank you!

.exists? is a method from ActiveRecord, not on Array.
If you want to test for empty arrays, you probably want to do
somefile.puts schedule["self"] unless schedule["escalation_policies"].empty?
If you want to test for any value at all, just doing
somefile.puts schedule["self"] if schedule["escalation_policies"]
should work

Try:
if schedule.has_key?("escalation_policies")
You could also test:
if schedule["escalation_policies"]
which would return false not only if the key does not exist, but also if it does exist, and its corresponding value is nil.
If the absence of values will always be represented by an empty array ([]), then instead you can use schedule["escalation_policies"].empty? as mentioned by Rick Sullivan in his answer, or schedule["escalation_policies"].any? to test for an array size > 0.

Related

How can I query for multiple values after a wildcard?

I have a json object like so:
{
_id: "12345",
identifier: [
{
value: "1",
system: "system1",
text: "text!"
},
{
value: "2",
system: "system1"
}
]
}
How can I use the XDevAPI SearchConditionStr to look for the specific combination of value + system in the identifier array? Something like this, but this doesn't seem to work...
collection.find("'${identifier.value}' IN identifier[*].value && '${identifier.system} IN identifier[*].system")
By using the IN operator, what happens underneath the covers is basically a call to JSON_CONTAINS().
So, if you call:
collection.find(":v IN identifier[*].value && :s IN identifier[*].system")
.bind('v', '1')
.bind('s', 'system1')
.execute()
What gets executed, in the end, is (simplified):
JSON_CONTAINS('["1", "2"]', '"2"') AND JSON_CONTAINS('["system1", "system1"]', '"system1"')
In this case, both those conditions are true, and the document will be returned.
The atomic unit is the document (not a slice of that document). So, in your case, regardless of the value of value and/or system, you are still looking for the same document (the one whose _id is '12345'). Using such a statement, the document is either returned if all search values are part of it, and it is not returned if one is not.
For instance, the following would not yield any results:
collection.find(":v IN identifier[*].value && :s IN identifier[*].system")
.bind('v', '1')
.bind('s', 'system2')
.execute()
EDIT: Potential workaround
I don't think using the CRUD API will allow to perform this kind of "cherry-picking", but you can always use SQL. In that case, one strategy that comes to mind is to use JSON_SEARCH() for retrieving an array of paths corresponding to each value in the scope of identifier[*].value and identifier[*].system i.e. the array indexes and use JSON_OVERLAPS() to ensure they are equal.
session.sql(`select * from collection WHERE json_overlaps(json_search(json_extract(doc, '$.identifier[*].value'), 'all', ?), json_search(json_extract(doc, '$.identifier[*].system'), 'all', ?))`)
.bind('2', 'system1')
.execute()
In this case, the result set will only include documents where the identifier array contains at least one JSON object element where value is equal to '2' and system is equal to system1. The filter is effectively applied over individual array items and not in aggregate, like on a basic IN operation.
Disclaimer: I'm the lead developer of the MySQL X DevAPI Connector for Node.js

How to access the key of a jsoncpp Value

I kind of feel stupid for asking this, but haven't been able to find a way to get the key of a JSON value. I know how to retrieve the key if I have an iterator of the object. I also know of operator[].
In my case the key is not a known value, so can't use get(const char *key) or operator[]. Also can't find a getKey() method.
My JSON looks like this:
{Obj_Array: [{"122":{"Member_Array":["241", "642"]}}]}
For the piece of code to parse {"122":{"Member_Array":["241", "642"]}} I want to use get_key()-like function just to retrieve "122" but seems like I have to use an iterator which to me seems to be overkill.
I might have a fundamental lack of understanding of how jsoncpp is representing a JSON file.
First, what you have won't parse in JsonCPP. Keys must always be enclosed in double quotes:
{"Obj_Array": [{"122":{"Member_Array":["241", "642"]}}]}
Assuming that was just an oversight, if we add whitespace and tag the elements:
{
root-> "Obj_Array" : [
elem0-> {
key0-> "122":
val0-> {
key0.1-> "Member_Array" :
val0.1-> [
elem0.1.0-> "241",
elem0.1.1-> "642" ]
}
}
]
}
Assuming you have managed to read your data into a Json::Value (let's call it root), each of the tagged values can be accessed like this:
elem0 = root[0];
val0 = elem0["122"]
val0_1 = val0["Member_Array"];
elem0_1_0 = val0_1[0];
elem0_1_1 = val0_1[1];
You notice that this only retrieves values; the keys were known a priori. This is not unusual; the keys define the schema of the data; you have to know them to directly access the values.
In your question, you state that this is not an option, because the keys are not known. Applying semantic meaning to unknown keys could be challenging, but you already came to the answer. If you want to get the key values, then you do have to iterate over the elements of the enclosing Json::Value.
So, to get to key0, you need something like this (untested):
elem0_members = elem0.getMemberNames();
key0 = elem0_members[0];
This isn't production quality, by any means, but I hope it points in the right direction.

Cannot merge the following node because of null property value for 'src': (:Node {src: null})

I am fairly new to neo4j and I want to write a query which reads .json format and create a graph of the nodes. Below is my query which is successful in a file where there is no null property and unsuccessful when I have null property in my json file.
CALL apoc.load.json("file:/graph-phase1-labelled.json") YIELD value
UNWIND value.nodes as nodes
UNWIND nodes.properties as prop
MERGE(n1:Node{src:prop.sourceIP})
MERGE(n2:Node{dst:prop.destIP})
WITH n1,n2,prop
MERGE (n1)-[:CONNECTED_TO]->(n2)
RETURN n1,n2,prop
Anyone has any idea of what might solve the issue?
When creating properties in Neo4j you cannot have null properties.
There are a number of ways to work around this, but a quick option to just get some data in could be to use coalesce() function, which will use the first non-null value it hits, e.g.
CALL apoc.load.json("file:/graph-phase1-labelled.json") YIELD value
UNWIND value.nodes as nodes
UNWIND nodes.properties as prop
MERGE(n1:Node{src:coalesce(prop.sourceIP,"No IP")})
MERGE(n2:Node{dst:coalesce(prop.destIP, "No IP"})
WITH n1,n2,prop
MERGE (n1)-[:CONNECTED_TO]->(n2)
RETURN n1,n2,prop
Thanks for your answer, the issue was that the dump that I was trying to build the graph upon had some null properties and I had to ignore them to go ahead with the rest of the nodes. the "No IP" did not work but I managed to solve it
by below:
call apoc.load.json("file:/graph-phase1-labelled1.json") yield value
unwind value.nodes as nodes
unwind nodes.properties as prop
with prop where prop.sourceIP is not null
with prop where prop.destIP is not null
merge(n1:Node{src:prop.sourceIP})
merge(n2:Node{dest:prop.destIP})
with prop,n1,n2
merge (n1)-[ :connected_to]->(n2)
return n1,n2,prop

How to conditionally return specific value with another in JSONPath?

I've got an object like this one:
{
"content": {
"iteration_size": 1
}
}
I need a JSONPath which returns null if the value of next_item is exactly 1, or the value of iteration_size otherwise. So the above should return null and "iteration_size": 2 should return 2. Is this possible in JSONPath?
I've tried variations on $.content[?(#.iteration_size == 1)].iteration_size, but the two online evaluators I've tried even disagree on the results of several of my attempts.
The use case is the AWS Batch API, where the array size must be either null or a number between 2 and 10,000.
AWS Support suggested that this was not possible, and that I should instead use a branch in the step function. I ended up replacing this:
.next(batch_submit_job)
[…]
with this:
.next(
aws_stepfunctions.Choice(self, "check_maybe_array")
.when(
aws_stepfunctions.Condition.number_equals("$.content.iteration_size", 1),
single_batch_submit_job,
)
.otherwise(array_batch_submit_job)
.afterwards()
)
where only array_batch_submit_job has an array_size. Note how the rest of the step function ended up wrapped inside the last next() call rather than at the top level.

(*it).second. How this keyword works?

for(it=visited.begin(); it!=visited.end();++it)
{
if((*it).second>ttl){
++count;
}
}
What does the line if((*it).second>ttl) means here ?
For better understanding see this code please .... http://ideone.com/NY4ofJ .
Thanks in Advance .
A map is a collection of pair ; with a key and a value. To access to the key you use the member first and to access to the value you use member second.
(*it).second or it->second dereference the iterator and get the second value of the pair contains in the map.
So, the value contained by the iterator is tested with the value contained by the ttl variable.
The line in the question points to the second value of a Map or Pair ... for more :
See Here