Attempting to retrieve a value from a JSON array in Groovy - json

I have a JSON object with an array (it is from the body of an HTTP response) that looks similar to the following:
{"people": [
{
"name": "john",
"city": "chicago",
"age": "22"
},
{
"name": "gary",
"city": "florida",
"age": "35"
},
{
"name": "sal",
"city": "vegas",
"age": "18"
}
]}
I'm trying to retrieve the "city" or "age" values by looking for a "name." e.g., when "name" = "sal," I'd expect to get "vegas" to be returned if I was asking for "city" or "18 if I had requested for "age." I'm attempting to do this in Groovy.
Don't even know where to start with the code. First time dealing with a JSON array. Any assistance is much appreciated.

I would recommend starting by reading Parsing and producing JSON documentation page. You will learn about the powerful groovy.json.JsonSlurper class that allows you to work with JSON documents efficiently.
When you create a JSON object representation with a method like:
def json = new JsonSlurper().parseText(rawJson)
You can access JSON document fields in the same way you access object properties. For instance, json.people will return you a list of people. Then, you can call the method like find(predicate) which returns a first result that matches the given predicate from a list. In this case, you can call something like:
def person = json.people.find { it.name == "sal" }
The it is a variable that keeps a reference to the object in the iteration process. It means that find iterates the list and searches for the first object that matches it.name == "sal".
When you find the person associated with the name, you can extract city and age fields in the same way as you would access object fields, e.g.
println person.age // prints 18
println person.city // prints vegas
Here is the full example:
import groovy.json.JsonSlurper
def rawJson = '''{"people": [
{
"name": "john",
"city": "chicago",
"age": "22"
},
{
"name": "gary",
"city": "florida",
"age": "35"
},
{
"name": "sal",
"city": "vegas",
"age": "18"
}
]}'''
def json = new JsonSlurper().parseText(rawJson) // creates JSON object
def person = json.people.find { it.name == "sal" } // finds the first person with name "sal"
assert person.city == "vegas" // calling person.city returns a city name
assert person.age == "18" // calling person.age returns age of a person
To learn more about processing JSON documents with Groovy, consider reading the documentation page I attached above. It will help you understand more complex use cases, and it will help you gain confidence in working with parsing JSON documents using Groovy. I hope it helps.

Related

JSON query matching

For the given input JSON:
{
"person": {
"name": "John",
"age": 25
},
"status": {
"title": "assigned",
"type": 3
}
}
I need to build a string query that I could use to answer if the given JSON matches it or not. For example if the given person's name is "John" and his age is in the range of 20..30 and his status is not 4.
I need the query to be presented as a string and a commonly known library that can run it. I need it on multiple platforms (iOS, Android, Xamarin). I've tried JSON Path and JSON schemas, but didn't really figure out if it's able to achieve that with them. JSON Path seems to be specified on finding a single value in the JSON by a certain condition and JSON Schema mostly checks for the data structure and types.
Ok, found the solution. If I format the whole input object as a single-element array like that:
[
{
"person": {
"name": "John",
"age": 25
},
"status": {
"title": "assigned",
"type": 3
}
}
]
That will allow me to use JSON Path expressions:
$[?(#.person.name == 'John' && #.person.age >= 20 && #.status.type != 4)]
Basically if it doesn't match there won't be a result.

How to escape "#" when reading from a JSON response?

Let's say I have below sample JSON response from which I want to extract value for "#type":
{
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"phoneNumbers": [
{
"#type" : "iPhone",
"number": "0123-4567-8888"
},
{
"#type" : "home",
"number": "0123-4567-8910"
}
]
}
Validated using:- http://jsonpath.com/
This works for "number":
$.phoneNumbers.[number]
But cannot get value for "#type":
$.phoneNumbers.[#type]
Tried multiple ways but no luck.
Thanks!
Edits:- added another value in the array for "home", now indexing logic [0,1] doesn't work. Even tried with [:] to fetch all values, but no luck.
You can read in this documentation:
Please note, that the return value of jsonPath is an array, which is
also a valid JSON structure.
So basically it always returns an array.
var phoneTypes = jsonPath(json,"$.phoneNumbers.[#type]");
result
["iPhone","home"]
if you want one phone you have to use phoneTypes[0] for iPhone
but I higly recommend you to fix your json using this code
var fixedJson= JSON.parse(JSON.stringify(json).replaceAll("\"#type\"","\"type\"" ));
in this case you can use the real search
var homePhone = jsonPath(fixedJson,"$.phoneNumbers[?(#.type =='home')]")[0].number;
output
0123-4567-8910

get by id from local json http

I have fake users.json file and I can http.get to list the array of json.
Since I want to get the particular user by id and haven't stored the data in the database, instead just use the fake json data.
[
{
"id": "cb55524d-1454-4b12-92a8-0437e8e6ede7",
"name": "john",
"age": "25",
"country": "germany"
},
{
"id": "ab55524d-1454-4b12-92a8-0437e8e6ede8",
"name": "tom",
"age": "28",
"country": "canada"
}
]
I can do this stuff if the data is stored in the database, but not sure how to proceed with the fake json data.
Any help is appreciated.
Thanks
If you need the json as raw data, for just fake data, You can simply require it and use it as object..
const JsonObj = require('path/to/file.json')
console.log(JsonObj[0].id) // <-- cb55524d-1454-4b12-92a8-0437e8e6ede7
Plus, if you need more dynamic solution, there is a good JSON-server you can easily use for testing and so: check this git repo
var _ = require('underscore');
var dummyJson = [
{
"id": "cb55524d-1454-4b12-92a8-0437e8e6ede7",
"name": "john",
"age": "25",
"country": "germany"
},
{
"id": "ab55524d-1454-4b12-92a8-0437e8e6ede8",
"name": "tom",
"age": "28",
"country": "canada"
}
]
var requiredID = "cb55524d-1454-4b12-92a8-0437e8e6ede7";
var reuiredObject = _.find(dummyJson, function (d) {
return d.id === requiredID;
})
Get JSON object using JSON.parse('users.json') and store it in a variable users.
Loop through array of users using for .. in and using if condition on id update the object if required.
Stringify the updated users object using JSON.stringify(users); and write this string to users.json file using fs.write() module in NodeJS so you will have updated objects in your json file.

How do I call a specific key in a list containing nested dictionaries?

I'm playing around with python and JSON files. I'm doing a simple game as a learning project, but I can't fetch a nested key in a list on demand when I want to. In the below example I'm trying to get the name of the player.
This is the JSON file (player_sheet_daniel.json):
[
{
"sheet_header": {
"player name": "Daniel",
"character name": "Ulrik the Blob"
}
},
{
"prim_attr": {
"STR": "11",
"DEX": "12",
"HP": "15",
"SKI": "16"
}
}
]
I've tried:
import json
with open('player_sheet_daniel.json','r') as sheet_json:
sheet_py = json.load(sheet_json)
for section in sheet_py:
print(section['sheet_header']['player name'])
I get: KeyError: 'sheet_header'.
Your JSON example is an array which wraps two objects. So, the correct python syntax would be :
import json
with open('player_sheet_daniel.json','r') as sheet_json:
sheet_py = json.load(sheet_json)
section = sheet_py[0]
print(section['sheet_header']['player name'])

Parsing and manipulating json in Scala

I have this JSON that is returned from a REST-service I'm using.
{
"id": "6804",
"signatories": [
{
"id": "12125",
"fields": [
{
"type": "standard",
"name": "fstname",
"value": "John"
},
{
"type": "standard",
"name": "sndname",
"value": "Doe"
},
{
"type": "standard",
"name": "email",
"value": "john.doe#somwhere.com"
},
{
"type": "standard",
"name": "sigco",
"value": "Company"
}
]
}
]
}
Currently I'm looking into a way to parse this with json4s, iterating over the "fields" array, to be able to change the property "value" of the different objects in there. So far I've tried a few json libs and ended up with json4s.
Json4s allows me to parse the json into a JObject, which I can try extract the "fields" array
from.
import org.json4s._
import org.json4s.native.JsonMethods._
// parse to JObject
val data = parse(json)
// extract the fields into a map
val fields = data \ "signatories" \ "fields"
// parse back to JSON
println(compact(render(fields)))
I've managed to extract a Map like this, and rendered it back to JSON again. What I can't figure out though is, how to loop through these fields and change the property "value" in them?
I've read the json4s documentation but I'm very new to both Scala and it's syntax so I'm having a difficult time.
The question becomes, how do I iterate over a parsed JSON result, to change the property "value"?
Here's the flow I want to achieve.
Parse JSON into iterable object
Loop through and look for certain "names" and change their value, for example fstname, from John to some other name.
Parse it back to JSON, so I can send the new JSON with the updated values back.
I don't know if this is the best way to do this at all, I'd really appreciate input, maybe there's an easier way to do this.
Thanks in advance,
Best regards,
Stefan Konno
You can convert the json into an array of case class which is the easiest thing to do. For example: you can have case class for Fields like
case class Field(`type`: String, name: String, value: String)
and you can convert your json into array of fields like read[Array[Field]](json) where json is
[
{
"type": "standard",
"name": "fstname",
"value": "John"
},
...
]
which will give you an array of fields. Similarly, you can model for your entire Json.
As now you have an array of case classes, its pretty simple to iterate the objects and change the value using case classes copy method.
After that, to convert the array of objects into Json, you can simply use write(objects) (read and write functions of Json4s are available in org.json4s.native.Serialization package.
Update
To do it without converting it into case class, you can use transformField function
parse(json).transformField{case JField(x, v) if x == "value" && v == JString("Company")=> JField("value1",JString("Company1"))}