I'm trying to parse a JSON-File in my gradle task.
CODE:
def jsonFile = "../files/json/myJSON.json"
def list = new JsonSlurper().parseText(jsonFile)
JSON - FILE
{
"prepare": {
"installed": [],
"uninstalled": []
},
"config": {
"files": []
}
}
But the code gives me the following exception:
Lexing failed on line: 1, column: 1, while reading '.', no possible valid JSON value or punctuation could be recognized.
And I don't understand why, I also validated my JSON-File on http://jsonlint.com/ and it says that it is a valid JSON!
Above code is trying to parse the string ../files/json/myJSON.json as JSON. Instead use:
def jsonFile = new File("../files/json/myJSON.json")
def map = new JsonSlurper().parse(jsonFile)
Related
I am trying to write a small JSON script that parses JSON files. I need to include multiple variables in the code but currently, I'm stuck since f string does not seem to be working as I expected. Here is an example code:
import json
test = 10
json_data = f'[{"ID": {test},"Name":"Pankaj","Role":"CEO"}]'
json_object = json.loads(json_data)
json_formatted_str = json.dumps(json_object, indent=2)
print(json_formatted_str)
The above code returns an error:
json_data = f'[{"ID": { {test} },"Name":"Pankaj","Role":"CEO"}]'
ValueError: Invalid format specifier
Could you, please let me know how can I add variables to the JSON?
Thank you.
You can put extra{ and } to your string:
import json
test = 10
json_data = f'[{{"ID": {test},"Name":"Pankaj","Role":"CEO"}}]'
json_object = json.loads(json_data)
json_formatted_str = json.dumps(json_object, indent=2)
print(json_formatted_str)
Prints:
[
{
"ID": 10,
"Name": "Pankaj",
"Role": "CEO"
}
]
This is sort of data I got in my json file
{"globals":{"code":"1111","country_code":"8888","hits":80,"extra_hit":1,"keep_money":true},"time_window":{"from":"2020.12.14 08:40:00","to":"2020.12.14 08:45:00"},"car":{"have":"nope"}}
After I run it through this groovy code in jmeter:
import groovy.json.JsonSlurper
import groovy.json.JsonBuilder
import groovy.json.JsonOutput
def jsonSlurper = new JsonSlurper().parse(new File("C:/pathToFile/test.json"))
log.info(jsonSlurper.toString())
jsonSlurper.globals.hits = 70
jsonSlurper.time_window.from = "2020.12.14 08:42:00"
jsonSlurper.time_window.to = "2020.12.14 08:48:00"
def builder = new JsonBuilder(jsonSlurper)
log.info(builder.toString())
def json_str = JsonOutput.toJson(builder)
def json_beauty = JsonOutput.prettyPrint(json_str)
log.info(json_beauty.toString())
File file = new File("C:/pathToFile/test.json")
file.write(json_beauty)
the json file is updated, but all data are wrapped in new object "content"
"content": {
"globals": {
"code":"1111",
"country_code": "8888",
"hits": 70,
"extra_hit": 1,
"keep_money": true
},
"time_window": {
"from": "2020.12.14 08:42:00",
"to": "2020.12.14 08:48:00"
},
"car": {
"have": "nope"
}
}
}
How to avoid that wrapping into "content" object?
Copying and pasting the code from Internet without having any idea what it is doing is not the best way to proceed, at some point you will end up running a Barmin's patch
My expectation is that you're looking for JsonBuilder.toPrettyString() function so basically everything which goes after this line:
def builder = new JsonBuilder(jsonSlurper)
can be replaced with:
new File("C:/pathToFile/test.json").text = builder.toPrettyString()
More information:
Apache Groovy: Parsing and producing JSON
Apache Groovy - Why and How You Should Use It
I try to read JSON from file, get values, transform them and back write to new file.
{
"metadata": {
"info": "important info"
},
"timestamp": "2018-04-06T12:19:38.611Z",
"content": {
"id": "1",
"name": "name test",
"objects": [
{
"id": "1",
"url": "http://example.com",
"properties": [
{
"id": "1",
"value": "1"
}
]
}
]
}
}
Above is a JSON that I read from file.
Below I attach a python program that gets values, creates new JSON and write it to file.
import json
from pprint import pprint
def load_json(file_name):
return json.load(open(file_name))
def get_metadata(json):
return json["metadata"]
def get_timestamp(json):
return json["timestamp"]
def get_content(json):
return json["content"]
def create_json(metadata, timestamp, content):
dct = dict(__metadata=metadata, timestamp=timestamp, content=content)
return json.dumps(dct)
def write_json_to_file(file_name, json_content):
with open(file_name, 'w') as file:
json.dump(json_content, file)
STACK_JSON = 'stack.json';
STACK_OUT_JSON = 'stack-out.json'
if __name__ == '__main__':
json_content = load_json(STACK_JSON)
print("Loaded JSON:")
print(json_content)
metadata = get_metadata(json_content)
print("Metadata:", metadata)
timestamp = get_timestamp(json_content)
print("Timestamp:", timestamp)
content = get_content(json_content)
print("Content:", content)
created_json = create_json(metadata, timestamp, content)
print("\n\n")
print(created_json)
write_json_to_file(STACK_OUT_JSON, created_json)
But the problem is that create json is not correct. Finally as result I get:
"{\"__metadata\": {\"info\": \"important info\"}, \"timestamp\": \"2018-04-06T12:19:38.611Z\", \"content\": {\"id\": \"1\", \"name\": \"name test\", \"objects\": [{\"id\": \"1\", \"url\": \"http://example.com\", \"properties\": [{\"id\": \"1\", \"value\": \"1\"}]}]}}"
It is not that what I want to achieve. It's not correct JSON. What do I wrong?
Solution:
Change the write_json_to_file(...) method like this:
def write_json_to_file(file_name, json_content):
with open(file_name, 'w') as file:
file.write(json_content)
Explanation:
The problem is, that when you're calling write_json_to_file(STACK_OUT_JSON, created_json) at the end of your script, the variable created_json contains a string - it's the JSON representation of the dictionary created in the create_json(...) function. But inside the write_json_to_file(file_name, json_content), you're calling:
json.dump(json_content, file)
You're telling the json module write the JSON representation of variable json_content (which contains a string) into the file. And JSON representation of a string is a single value encapsulated in double-quotes ("), with all the double-quotes it contains escaped by \.
What you want to achieve is to simply write the value of the json_content variable into the file and not have it first JSON-serialized again.
Problem
You're converting a dict into a json and then right before you write it into a file, you're converting it into a json again. When you retry to convert a json to a json it gives you the \" since it's escaping the " since it assumes that you have a value there.
How to solve it?
It's a great idea to read the json file, convert it into a dict and perform all sorts of operations to it. And only when you want to print out an output or write to a file or return an output you convert to a json since json.dump() is expensive, it adds 2ms (approx) of overhead which might not seem much but when your code is running in 500 microseconds it's almost 4 times.
Other Recommendations
After seeing your code, I realize you're coming from a java background and while in java the getThis() or getThat() is a great way to module your code since we represent our code in classes in java, in python it just causes problems in the readability of the code as mentioned in the PEP 8 style guide for python.
I've updated the code below:
import json
def get_contents_from_json(file_path)-> dict:
"""
Reads the contents of the json file into a dict
:param file_path:
:return: A dictionary of all contents in the file.
"""
try:
with open(file_path) as file:
contents = file.read()
return json.loads(contents)
except json.JSONDecodeError:
print('Error while reading json file')
except FileNotFoundError:
print(f'The JSON file was not found at the given path: \n{file_path}')
def write_to_json_file(metadata, timestamp, content, file_path):
"""
Creates a dict of all the data and then writes it into the file
:param metadata: The meta data
:param timestamp: the timestamp
:param content: the content
:param file_path: The file in which json needs to be written
:return: None
"""
output_dict = dict(metadata=metadata, timestamp=timestamp, content=content)
with open(file_path, 'w') as outfile:
json.dump(output_dict, outfile, sort_keys=True, indent=4, ensure_ascii=False)
def main(input_file_path, output_file_path):
# get a dict from the loaded json
data = get_contents_from_json(input_file_path)
# the print() supports multiple args so you don't need multiple print statements
print('JSON:', json.dumps(data), 'Loaded JSON as dict:', data, sep='\n')
try:
# load your data from the dict instead of the methods since it's more pythonic
metadata = data['metadata']
timestamp = data['timestamp']
content = data['content']
# just cumulating your print statements
print("Metadata:", metadata, "Timestamp:", timestamp, "Content:", content, sep='\n')
# write your json to the file.
write_to_json_file(metadata, timestamp, content, output_file_path)
except KeyError:
print('Could not find proper keys to in the provided json')
except TypeError:
print('There is something wrong with the loaded data')
if __name__ == '__main__':
main('stack.json', 'stack-out.json')
Advantages of the above code:
More Modular and hence easily unit testable
Handling of exceptions
Readable
More pythonic
Comments because they are just awesome!
def json = '{"book": [{"id": "01","language": "Java","edition": "third","author": "Herbert Schildt"},{"id": "07","language": "C++","edition": "second","author": "E.Balagurusamy"}]}'
Using Groovy code, how to get the "id" values printed for "book" array?
Output:
[01, 07]
This is the working example using your input JSON.
import groovy.json.*
def json = '''{"book": [
{"id": "01","language": "Java","edition": "third","author": "Herbert Schildt"},
{"id": "07","language": "C++","edition": "second","author": "E.Balagurusamy"}
]
}'''
def jsonObj = new JsonSlurper().parseText(json)
println jsonObj.book.id // This will return the list of all values of matching key.
Demo here on groovy console : https://groovyconsole.appspot.com/script/5178866532352000
Below is my JSON script.
PRAMS.json
{
"JSON" : {
"test": "iTEST",
"testname": "BOV-VDSL-link-Rateprofile-CLI-Test-1",
"params": [
{
"n2x_variables / config_file": "C:/Program Files (x86)/Agilent/N2X/RouterTester900/UserData/config/7.30 EA SP1 Release/OSP Regression/BOV/Bov-data-1-single-rate-profile.xml"
},
{
"n2x_variables / port_list": "303/4 303/1"
}
]
}
}
Below is my groovy script and I am sending params.json script to the same groovy script.
parseJSON.groovy
import groovy.json.JsonSlurper
def jsonFile = new File("../var/PARAMS.json")
def keys = new JsonSlurper().parse("jsonFile.text")
println keys.keySet()
I am getting below error :
****No signature of method: groovy.json.JsonSlurper.parse() is applicable for argument types: (java.lang.String) values: [jsonFile.text]****
Can any one please help me ?
Thanks for reply, I am new to this json.
I am unable to share screen shot, showing error message when I am trying to upload image but i can give total error message :
developer#cn-vm-yourname:~/Desktop/kramdeni/vars$ groovy parseJSON.groovy
Caught: groovy.lang.MissingMethodException: No signature of method: groovy.json.JsonSlurper.parse() is applicable for argument types: (java.lang.String) values: [jsonFile]
Possible solutions: parse(java.io.Reader), parseText(java.lang.String), use([Ljava.lang.Object;), wait(), grep(), any()
groovy.lang.MissingMethodException: No signature of method: groovy.json.JsonSlurper.parse() is applicable for argument types: (java.lang.String) values: [jsonFile]
Possible solutions: parse(java.io.Reader), parseText(java.lang.String), use([Ljava.lang.Object;), wait(), grep(), any()
at parseJSON.run(parseJSON.groovy:3)
developer#cn-vm-yourname:~/Desktop/kramdeni/v
and my expected output is to print only all values without keys in required order.
To get above result I wrote groovy script like below :
import groovy.json.JsonSlurper
label = "test testname params"
def jsonFile = new File('PARAMS.json')
def par = new JsonSlurper().parse(jsonFile)
println keys.keySet()
def command = ""
keys = label.split(" ")
println "keys: " + keys
for (key in keys) {
command += par[key] + " "
}
println "command: " + command
import groovy.json.JsonSlurper
def src = new File("MYPATH/MY.json")
//next line downloads json from URL:
//def src = new URL("http://date.jsontest.com")
def json = new JsonSlurper().parse( src.newInputStream() )
json.each{ k,v-> println "$k = $v" }
try it:
https://groovy-playground.appspot.com/#?load=ccceffd570c6ee176bc6f1fcdafdcbe0
if you have exception
groovy.lang.MissingMethodException: No signature of method:
groovy.json.JsonSlurper.parse() is applicable for argument types:
(java.io.BufferedInputStream)
Possible solutions: parse(java.io.Reader) ...
that means you have quite old version of groovy, however it suggests solution - try to get reader from file:
def src = new File("MYPATH/MY.json")
def json = new JsonSlurper().parse( src.newReader("UTF-8") )
json.each{ k,v-> println "$k = $v" }
but to continue you have to find version of your groovy, then find documentation for your version and continue developing referencing it
for example in groovy 1.8.6 there are only two parse methods in JsonSlurper:
http://docs.groovy-lang.org/1.8.6/html/api/groovy/json/JsonSlurper.html
and in the latest groovy much more...
http://docs.groovy-lang.org/latest/html/gapi/groovy/json/JsonSlurper.html