Create json object and append json into existing json file using Groovy - json

I'm pretty new to Groovy (and json) and plauing arround to get the expected solution. But couldn't be able to achive it.
What I'm trying to do is parse an existing json file and then add/append additional entries as in below example:
Original Json File:
{
"stack-1": {
"name": "demo",
"createdAt": "11:00 PM",
"owner": "sarva",
"dbName": "DB"
}
}
New Json Content from Json Builder:
{
"stack-2": {
"name": "demo-2",
"createdAt": "15:00 PM",
"owner": "bhowma",
"dbName": "DB2"
}
}
Intended Json output after merge:
{
"stack-1": {
"name": "demo",
"createdAt": "11:00 PM",
"owner": "sarva",
"dbName": "DB"
},
"stack-2": {
"name": "demo-2",
"createdAt": "15:00 PM",
"owner": "Bhowma",
"dbName": "DB2"
}
}
I've tried many variations on the following code snippet but still not quite getting the right format for my intended output.
import groovy.json.*
def number = 2
def name = "demo-2"
def createdAt = "15:00 PM"
def owner = "bhowma"
def db_name = "DB2"
// here I am loading an old json file
def jsonSlurper = new JsonSlurper()
def json = jsonSlurper.parse(new File('/tmp/sarva.json'))
// Here I am building a new JSON with the above parameters.
def builder = new JsonBuilder()
def root = builder "stack-$number": [name: name, createdAt: createdAt, owner: owner, dbName: db_name]
def newJson = jsonSlurper.parseText(builder.toPrettyString())
println(json.getClass())
println(newJson.getClass())
print json
print builder
Currently, I am able to see below the o/p from both json & builder.toPrettyString() and their classes. but I am not able to merge them as intended. and I want this merge to work for as many json objects as I pass.
Current output looks like below
class groovy.json.internal.LazyMap
class groovy.json.internal.LazyMap
[stack-1:[createdAt:11:00 PM, dbName:DB, name:demo, owner:sarva]]
{"stack-2":{"name":"demo-2","createdAt":"15:00 PM","owner":"Bhowma","dbName":"DB-2"}}
Any help sorting this would be much appreciated.

Ignoring your example being incomplete, you've parsed the original JSON into a Map, so just add the new element to the map
// Here I am building a new Map with the above parameters.
json += ["stack-$number": [name: name, createdAt: createdAt, owner: owner, dbName: db_name]]
And then print out the new json from this map
println new JsonBuilder(json).toPrettyString()

Related

Attempting to retrieve a value from a JSON array in Groovy

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.

Parsing json in json Groovy Katalon Studio

I got a JSON text which I should parse, but for some reason I can't parse it because it has another array inside. My JSON looks like that:
{
"statementId": "1",
"movements": [
{
"id": 65,
"date": "2019-02-05",
"number": 32,
"balance": -4.62,
"purpose": "1"
},
{
"id": 1,
"date": "2019-02-05",
"number": 22,
"balance": -3,
"purpose": "23"
},
{
"id": 32,
"date": "2019-02-05",
"number": 12,
"balance": -11,
"purpose": "2"
}
],
"startPointer": "1122",
"endPointer": "3333"
}
I am using JsonSlurper. I want to know if it is possible to catch all the data inside "movements", I have tried to use this script:
JsonSlurper slurper = new JsonSlurper()
Map parsedJson = slurper.parseText(bodyContent)
String parsed_movements = parsedJson["movements"]
I have no problem with parsing single strings, like statementId or startPointer, but when I try to parse movements with my script it gives me result as null. I have also tried parsedJson["movements"][0] to catch first movement but it also gives me an error.
I have found a lot of things about json parsers on internet and also on stackoverflow but nothing what I seek. I really don't think that it is a duplicate question.
EDIT: I tried for statement also to put each object in array like that:
def movements_array = []
for(def i = 0; i < parsedJson.movements.size(); i++) {
movements_array << parsedJson.movements[i].id
println(movements_array)
}
But it gives me an error: Cannot invoke method size() on null object, because parsedJson.movements is null.
When you do:
String parsed_movements = parsedJson["movements"]
You're sticking a map into a String, which isn't what you want.
Given the json in your question, you can just do
def movementIds = new JsonSlurper().parseText(bodyContents).movements.id
To get a list of [65, 1, 32]
If you're getting NPEs I assume the json isn't what you show in the question

CSV to JSON and add title

I have a csv document:
{
"epsilon_id": 194029423,
"weather": "cloudy",
"temperature": 27
},
{
"epsilon_id": 932856192,
"weather": "sunny",
"temperature": 31
}
I was wondering if there was a tool to make it into valid json where the field epsilon_id is the title for the data.
ex:
{
194029423: {
"weather": "cloudy",
"temperature": 27
},
932856192: {
"weather": "sunny",
"temperature": 31
}
}
I would prefer it to be a program (in whatever language) that I can run because I have 1,000 entries in my test sample and I will have tens of thousands in my final copy.
Any help would be much appreciated!
You are looking at JSON transformation, and ofcourse can be achieved with a custom programming. I can explain you how you can achieve this in Java, but functionally its gonna be the same for any programming of your choice.
Your input json will look like this:
[{
"epsilon_id": 194029423,
"weather": "cloudy",
"temperature": 27
},
{
"epsilon_id": 932856192,
"weather": "sunny",
"temperature": 31
}]
When you parse in java using popular Jackson library, you will get list of object for below class:
class Input
{
#JsonProperty(access = Access.WRITE_ONLY)
String epsilon_id,
String weather,
int temperature
}
Then you create a map object Map<Integer, Input>, populate data like below:
Map<Integer, Input> map = new HashMap<>();
for(Input obj : listOfInputs){
map.put(obj.epsilon_id, obj)
};
Serialize your result map using Jackson again to get your desired output format:
{
194029423: {
"weather": "cloudy",
"temperature": 27
},
932856192: {
"weather": "sunny",
"temperature": 31
}
}
If you are not very familiar with Java & Jackson JSON parsing, I found this tutorial with code sample, which will give you headstart.
import csv, json, os
# rename this file or pass it in as process.argv[2]
# then pipe output into another file. or
with open("./foo.csv") as f:
output = {}
for line in csv.DictReader(f):
key = line.pop("epsilon_id")
if output.has_key(key):
print("Duplicate Id -> {} ".format(key))
output[key] = line
# then pipe this output into another file.
print(json.dumps(output, indent=2))
# or write a file
with open("/tmp/foo.json",'w') as f:
json.dump(output, f)
Python makes it pretty easy : this will detect all types from a csv file.
demo : https://repl.it/#markboyle/UsableIcyFeed

Bash Parse JSON Objects jsawk

I´m trying to parse some JSON, which is the output of the Philips Hue API.
I found the tool jsawk, but somehow I´m not able to access the data inside the JSON Object.
The command:
... | jsawk 'return this.f709f9c0b-on-0.name'
works but unfortunately I don't have the ID of each object (e.g. f709f9c0b-on-0). Is there a way to access the object without knowing the ID and then to find out that ID. I tried to use "*" or Iterations of the objects but nothing was working.
Thanks in advance
The output looks like this:
{
"f709f9c0b-on-0": {
"name": "Badezimmer on 0",
"lights": [
"4"
],
"owner": "3e281978544fb15b42bc0e3a3f4ce3",
"recycle": true,
"locked": false,
"appdata": {},
"picture": "",
"lastupdated": "2016-02-17T17:20:06",
"version": 1
},
"69d313be0-on-0": {
"name": "Klavier on 0",
"lights": [
"1"
],
"owner": "3e281978544fb15b42bc0e3a3f4ce3",
"recycle": true,
"locked": false,
"appdata": {},
"picture": "",
"lastupdated": "2016-02-17T17:31:05",
"version": 1
},
...
}
f709f9c0b-on-0 is not a valid identifier due to the hyphens, so you can't use the dot notation. This might work (untested)
... | jsawk 'return this["f709f9c0b-on-0"].name'
I don't have jsawk, but jq can do it like this:
... | jq '.["f709f9c0b-on-0"].name'
Just for the rest of the world.
I solved the problem, by creating a .jar, which handles the problem. I find it much easier to do this in Java, than in bash.
I used this JSON-classes: https://github.com/stleary/JSON-java
Just download the files, create the package org.json and your good to go.
The Java Code, which worked for me is:
String JSON = "your JSON";
JSONObject jsonObject = new JSONObject(JSON);
ArrayList<ArrayList<String>> keyArray = new ArrayList<>();
Iterator<String> keys = jsonObject.keys(); //get all JSON keys
while (keys.hasNext()) { //for all keys do...
String key = (String) keys.next(); //get Current Key
//Now you can access the Object in the Object with:
jsonObject.getJSONObject(key).getString("name")
}
I hope this helps someone.

emberjs JSON format handling

I have an Employee model in my emberjs app, and I am trying to load the Employees content using a RESTful web service which come in the following format:
{
"Result": [
{
"EmployeeId": "1",
"EmployeeName": "Mark Smith",
"Active": 0,
"Dept": "Sales"
},
{
"EmployeeId": "2",
"EmployeeName": "John Smith",
"Active": 1,
"Dept": "Sales"
},
{
"EmployeeId": "3",
"EmployeeName": "Michael Smith",
"Active": 1,
"Dept": "Administration"
}
],
"ResultCount": 3
}
Here I am facing 3 problems:
Is it possible to read this JSON format and add it to the Employee model, I understand that "Result" should have been "Employees" but I have no control over the return JSON format so if it is possible to use "Result" that will be great. Any example on doing so is highly appreciated.
How can I handle "ResultCount"? Is there a way I can read it as part of Employee model?
How I can read "Active" in the app View as "Active" / "Not Active" instead of 0 or 1?
Thanks for your time
As pointed out by jasonpgignac, you'll need to write a custom serailizer/deserializer to get the data into ember-data.
Once you have your data loaded ResultCount isn't required. You should use the 'length' property on the returned collection.
As part of your serializer you'll want to convert 0/1 to false/true in your model. You can them add a property like:
activeLabel: ( ->
if #get('active')
'Active'
else
'Not Active'
).property('active')
and use this property in your templates.
As requested, here's a sample class from a project of mine:
App.StudentSerializer = DS.ActiveModelSerializer.extend
serializeBelongsTo: (record, json, relationship) ->
key = relationship.key
if key is 'attendance'
#serializeAttendance(record, json)
else
json["#{key}_id"] = record.get("#{key}.id")
serializeAttendance: (record, json) ->
attendance = record.get('attendance')
json['attendance'] = {}
['monday', 'tuesday', 'wednesday', 'thursday', 'friday'].forEach( (day) =>
json['attendance'][day] = attendance.get(day)
)
serializeHasMany: (record, json, relationship) ->
key = relationship.key
jsonKey = Ember.String.singularize(key) + '_ids'
json[jsonKey] = []
record.get(key).forEach( (item) ->
json[jsonKey].push(item.get('id'))
)
My store.coffee looks like:
App.Store = DS.Store.extend
# Override the default adapter with the `DS.ActiveModelAdapter` which
# is built to work nicely with the ActiveModel::Serializers gem.
adapter: '_ams'
App.ApplicationSerializer = DS.ActiveModelSerializer.extend()
You'll probably want to use the JsonAdapter and extend it if you don't have any control over the backend. As I said below, I haven't done deserialising but there should be the necessary hooks for you to convert into the format required by ember-data.