Parse multi level JSON with Ruby - json

I am trying to parse the JSON file below. The problem is I cannot return "Mountpoint" as a key. It only gets parsed as a value. This is the command I am using to parse it json_data = JSON.parse(readjson). The reason I guess that it's a key is because if I run json_data.keys only EncryptionStatus and SwitchName are returned. Any help would be greatly appreciated.
{
"EncryptionStatus": [
{
"MountPoint": "C:",
"VolumeStatus": "FullyEncrypted"
},
{
"MountPoint": "F:",
"VolumeStatus": "FullyEncrypted"
},
{
"MountPoint": "G:",
"VolumeStatus": "FullyEncrypted"
},
{
"MountPoint": "H:",
"VolumeStatus": "FullyEncrypted"
}
],
"SwitchName": [
"LAN",
"WAN"
]
}
I tried using dig as a part of my JSON.parse but that didn't seem to help me.

JSON data can have multiple levels.
Your JSON document is a
Hash (Dictionary/Map/Object in other languages) that has two keys ("EncryptionStatus", "SwitchName"),
The value for the "EncryptionStatsu" key is an Array of Hashes (with keys "MountPoint" and "VolumeStatus").
# assuming your JSON is in a file called "input.json"
data = File.read("input.json")
json = JSON.parse(data)
json["EncryptionStatus"].each do |encryption_status|
puts "#{encryption_status["MountPoint"]} is #{encryption_status["VolumeStatus"]}"
end
This will print out
C: is FullyEncrypted
F: is FullyEncrypted
G: is FullyEncrypted
H: is FullyEncrypted
If you want to access a specific item you can look at the dig method. E.g.
json.dig("EncryptionStatus", 3)
Would return the information for mountpoint "H"

Related

Using parsed json by JsonSlurper, how do I return a value based on another key value pair of the same node?

I have below JSON and want to fetch the value of "person1" and "person2" either into a map as a key-value pair or individually is also fine.
Expected Output: [attributes:["person1": "ROBERT", "person2": "STEVEN"]]
I started with JSON parsing and dont really have idea on what to do next?
def parsedJSON= new groovy.json.JsonSlurper().parseText(body)
JSON
"permutationsRequest":{
"attributes":[
{
"name":"person1",
"value":"ROBERT"
},
{
"name":"person2",
"value":"STEVEN"
}
]
}
}
def map = parsedJSON.permutationsRequest.attributes.collectEntries{ [it.name,it.value] }
println map.person2

extracting nested values from JSON using Ruby

I want to extract the individual values by key out of this JSON.
json = JSON.parse({ "streams": [ { "index": 0, "codec_name": "mpeg2video"} ] })
Using json['streams'].each do |codec_name| returns the whole first array back. I also tried identifying specific array number by json['streams'][1].each do |codec_name| and that errors.
Final output should return "mpeg2video"?
This is what worked. Had to drill down through the Array and Hash to get to it.
((json[''].each { |j| j['streams'] })[0])["codec_name"]
Since you appear to have an array of hashes in your JSON, you need to target the key codec_name. This should work:
# Assuming json_hash is a Hash that was returned by `JSON.parse()`
json_hash = { "streams": [ { "index": 0, "codec_name": "mpeg2video"} ] }
json_hash['streams'].each { |j| j['codec_name'] }
In this loop j is targeting the hash, and therefore you need j['codec_name']

Dynamically build json using groovy

I am trying to dynamically build some json based on data I retrieve from a database. Up until the opening '[' is the "root" I guess you could say. The next parts with name and value are dynamic and will be based on the number of results I get from the db. I query the db and then the idea was to iterate through the result adding to the json. Can I use jsonBuilder for the root section and then loop with jsonSlurper to add each additional section? Most of the examples I have seen deal with a root and then a one time "slurp" and then joining the two so wasn't sure if I should try a different method for looping and appending multiple sections.
Any tips would be greatly appreciated. Thanks.
{
"hostname": "$hostname",
"path": "$path",
"extPath": "$extPath",
"appName": "$appName",
"update": {"parameter": [
{
"name": "$name",
"value": "$value"
},
{
"name": "$name",
"value": "$value"
}
]}
}
EDIT: So what I ended up doing was just using StringBuilder to create the initial block and then append the subsequent sections. Maybe not the most graceful way to do it, but it works!
//Create the json string
StringBuilder json = new StringBuilder("""{
"hostname": "$hostname",
"path": "$path",
"extPath": "$extPath",
"appName": "$appName",
"update": {"parameter": ["""
)
//Append
sql.eachRow("""<query>""",
{ params ->
json.append("""{ "name": "params.name", "value": "params.value" },""");
}
)
//Add closing json tags
json.append("""]}}""")
If I got your explanation correctly and if the data is not very big (it can live in memory), I'd build a Map object (which is very easy to work with in groovy) and convert it to JSON afterwards. Something like this:
def data = [
hostname: hostname,
path: path,
extPath: extPath,
appName: appName,
update: [parameter: []]
]
sql.eachRow(sqlStr) { row ->
data.update.parameter << [name: row.name, value: row.value]
}
println JsonOutput.toJson(data)
If you're using Grails and Groovy you can utilize grails.converters.JSON.
First, define a JSON named config:
JSON.createNamedConfig('person') {
it.registerObjectMarshaller(Person) {
Person person ->
def output = [:]
output['name'] = person.name
output['address'] = person.address
output['age'] = person.age
output
}
}
This will result in a statically defined named configuration for the Object type of person. Now, you can simply call:
JSON.use('person') {
Person.findAll() as JSON
}
This will return every person in the database with their name, address and age all in one JSON request. I don't know if you're using grails as well in this situation though, for pure Groovy go with another answer here.

How can I extract fields from JSON only when three matching fields are present?

I want to extract employeid and result where deptcode, Name, and position are present.
{
"employeeid": 101,
"result": {
"deptcode": 0,
"Name": "Henry",
"position": "Administrator head."
}
}
My current code is:
i = beginIndex
temp = ""
value = ""
while i < endIndex
temp = dataMap[i].to_s.split(":")[1].strip()
value += "#{temp},"
i += 1
end
Extract Fields by Hash Key
If you have a valid JSON string, you can covert it to a Ruby hash and access fields by key. Using Enumerable#all? will enable you to only return a value if all fields are present. For example:
require 'json'
# Use a valid JSON string, or a native Ruby hash. We'll assume you're
# starting with a JSON string, although the following would be a valid
# Ruby hash object without parsing if not wrapped in quotes. YMMV.
json = <<~EOF
{
"employeeid": 101,
"result": {
"deptcode": 0,
"Name": "Henry",
"position": "Administrator head."
}
}
EOF
# Convert the JSON above to a Ruby hash.
hash = JSON.parse json
# Extract fields when all keys are present.
[ hash['employeeid'], hash['result'] ] if
hash['result'].keys.all? { |key| %w[deptcode Name position].include? key }
#=> [101, {"deptcode"=>0, "Name"=>"Henry", "position"=>"Administrator head."}]
This works fine with your corrected corpus. If you have an array of results, or a deeply-nested structure, then you'll need to do some additional coding to make it work. However, it works just fine with the refactored data given in the original post.

Groovy compare two json with unknown nodes names and values

I have a rest API to test and I have to compare two json responses. Below you can find a structure of the file. Both files to compare should contains the same elements but order might be different. Unfortunately the names, the type (simple, array) and the number of keys (root, nodeXYZ) are also not known.
{"root": [{
"node1": "value1",
"node2": "value1",
"node3": [
{
"node311": "value311",
"node312": "value312"
},
{
"node321": "value321",
"node322": "value322"
}
],
"node4": [
{
"node411": "value411",
"node412": "value413",
"node413": [ {
"node4131": "value4131",
"node4132": "value4131"
}],
"node414": []
}
{
"node421": "value421",
"node422": "value422",
"node423": [ {
"node4231": "value4231",
"node4232": "value4231"
}],
"node424": []
}]
"node5": [
{"node51": "value51"},
{"node52": "value52"},
]
}]}
I have found some useful information in
Groovy - compare two JSON objects (same structure) and return ArrayList containing differences
Getting node from Json Response
Groovy : how do i search json with key's value and find its children in groovy
but I could not combine it to an solution.
I thought the solution might look like this:
take root
get root children names
check if child has children and get their names
do it to the lowest leve child
With all names in place comparing should be easy (I guess)
Unfortunately I did not manage to get keys under root
Just compare the slurped maps:
def map1 = new JsonSlurper().parseText(document1)
def map2 = new JsonSlurper().parseText(document2)
assert map1 == map2
Try the JSONassert library: https://github.com/skyscreamer/JSONassert. Then you can use:
JSONAssert.assertEquals(expectedJson, actualJson, JSONCompareMode.STRICT)
And you will get nicely formatted deltas like:
java.lang.AssertionError: Resources.DbRdsLiferayInstance.Properties.KmsKeyId
Expected: kms-key-2
got: kms-key