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.
Related
I am currently implementing some test automation that uses a json POST to a REST API to initialize the test data in the SUT. Most of the fields I don't have an issue editing using information I found in another thread: Json handling in ROBOT
However, one of the sets of information I am editing is a dictionary of meta data.
{
"title": "Test Auotmation Post 2018-03-06T16:12:02Z",
"content": "dummy text",
"excerpt": "Post made by automation for testing purposes.",
"name": "QA User",
"status": "publish",
"date": "2018-03-06T16:12:02Z",
"primary_section": "Entertainment",
"taxonomy": {
"section": [
"Entertainment"
]
},
"coauthors": [
{
"name": "QA User - CoAuthor",
"meta": {
"Title": "QA Engineer",
"Organization": "That One Place"
}
}
],
"post_meta": [
{
"key": "credit",
"value": "QA Engineer"
},
{
"key": "pub_date",
"value": "2018-03-06T16:12:02Z"
},
{
"key": "last_update",
"value": "2018-03-06T16:12:02Z"
},
{
"key": "source",
"value": "wordpress"
}
]
}
Is it possible to use the Set to Dictionary Keyword on a dictionary inside a dictionary? I would like to be able to edit the value of the pub_date and last_update inside of post_meta, specifically.
The most straightforward way would be to use the Evaluate keyword, and set the sub-dict value in it. Presuming you are working with a dictionary that's called ${value}:
Evaluate $value['post_meta'][1]['pub_date'] = 'your new value here'
I won't get into how to find the index of the post_meta list that has the 'key' with value 'pub_date', as that's not part of your question.
Is it possible to use the Set to Dictionary Keyword on a dictionary inside a dictionary?
Yes, it's possible.
However, because post_meta is a list rather than a dictionary, you will have to write some code to iterate over all of the values of post_meta until you find one with the key you want to update.
You could do this in python quite simply. You could also write a keyword in robot to do that for you. Here's an example:
*** Keywords ***
Set list element by key
[Arguments] ${data} ${target_key} ${new_value}
:FOR ${item} IN #{data}
\ run keyword if '''${item['key']}''' == '''${target_key}'''
\ ... set to dictionary ${item} value=${new_value}
[return] ${data}
Assuming you have a variable named ${data} contains the original JSON data as a string, you could call this keyword like the following:
${JSON}= evaluate json.loads('''${data}''') json
set list element by key ${JSON['post_meta']} pub_date yesterday
set list element by key ${JSON['post_meta']} last_update today
You will then have a python object in ${JSON} with the modified values.
Should be a no brainer, but I'm can't seem to access the elements returned from Newtonsoft's json deserializer.
Example json:
{
"ns0:Test": {
"xmlns:ns0": "http:/someurl",
"RecordCount": "6",
"Record": [{
"aaa": "1",
"bbb": "2",
},
{
"aaa": "1",
"bbb": "2",
}]
}
}
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(somestring);
Stripping out the json up to the Record text, i can access the data without issue.
i.e. result.Recordcount
If i leave the json as shown above, can someone enlighten me how to access Recordcount?
All inputs appreciated. Thanks!
For those JSON properties that have punctuation characters or spaces (such that they cannot be made into valid C# property names), you can use square bracket syntax to access them.
Try this:
int count = result["ns0:Test"].RecordCount;
I am using QT 5.3. I have read various materials present online describing how to write json file,but no content describes it systematically and stepwise.
It would be really helpful if someone can explain the stepwise process of writing a json file in simple language since i am new to qt.
In my case i have a json file that already exists "LOM.json" with some content.How do i add new data to this.
{
"LOM": [
{
"LOM ID": 1,
"Source": "Open Internet",
"Content": "Complete Reference Java.pdf",
"Difficulty Level": "Hard",
"Type": "Text",
"Length": "Long",
"Topic-Proficiency": [
{
"Topic": "Programming",
"Proficiency": "E2"
},
{
"Topic": "Java",
"Proficiency": "E3"
}
]
},
{
"LOM ID": 2,
"Source": "Open Internet",
"Content": "www.LatexTutorial.com",
"Difficulty Level": "Medium",
"Type": "WebCourse",
"Length": "Medium",
"Topic-Proficiency": [
{
"Topic": "Latex",
"Proficiency": "E2"
}
]
}
]
}
Thanks.
You can't directly insert data into the middle of the document. You would need to read the document and write it out again. Let's look at how we'd go about this.
Assuming the current JSON you posted is in memory as a QByteArray, you create a QJsonDocument:-
QJsonDocument doc = QJsonDocument::fromJson(data); // where data is the current JSON
If we want to add another LOM object to the array. We get the first object, which is the array:-
QJsonObject rootObj = doc.object();
QJsonValue lomObj = rootObj.value("LOM");
if(!lomObj.isArray())
{
// array expected - handle error
}
QJsonArray lomArray = lomObj.toArray();
Now we have the array, we can create a new object
QJsonObj newObject;
newObject["LOM ID"] = 3;
newObject["Source"] = "Open Internet"
newObject["Content"] = "Some other content"
//etc...
And add this to the array
lomArray.push_back(newObject);
Finally, you can create a new document and get a byte array of the data to write to the file
QJsonDocument newDoc(obj);
QByteArray finalData = newDoc.toJson();
I finally got it done.
Actually the mistake was that while declaring the QJsonObject and QjsonArray,i was declaring them as pointer type that's why it was not allowing to insert qjsonobject to qjsonarray.
As far as writing to already existing json file is concerned,firstly the file is to be opened and content is to be read in qjsonarray or object.Next the changes to be done are appended to the read data(in qjson object or qjsonarray) and finally the new value is inserted to the read document by removing the previous one.
Thanks #merlin069 and this post -Qt modifying a JSON file.
I have a large JSON file that looks similar to the code below. Is there anyway I can iterate through each object, look for the field "element_type" (it is not present in all objects in the file if that matters) and extract or write each object with the same element type to a file? For example each user would end up in a file called user.json and each book in a file called book.json?
I thought about using javascript but to my knowledge js can't write to files, I also tried to do it using linux command line tools by removing all new lines, then inserting a new line after each "}," and then iterating through each line to find the element type and write it to a file. This worked for most of the data; however, where there were objects like the "problem_type" below, it inserted a new line in the middle of the data due to the nested json in the "times" element. I've run out of ideas at this point.
{
"data": [
{
"element_type": "user",
"first": "John",
"last": "Doe"
},
{
"element_type": "user",
"first": "Lucy",
"last": "Ball"
},
{
"element_type": "book",
"name": "someBook",
"barcode": "111111"
},
{
"element_type": "book",
"name": "bookTwo",
"barcode": "111111"
},
{
"element_type": "problem_type",
"name": "problem object",
"times": "[{\"start\": \"1230\", \"end\": \"1345\", \"day\": \"T\"}, {\"start\": \"1230\", \"end\": \"1345\", \"day\": \"R\"}]"
}
]
}
I would recommend Java for this purpose. It sounds like you're running on Linux so it should be a good fit.
You'll have no problems writing to files. And you can use a library like this - http://json-lib.sourceforge.net/ - to gain access to things like JSONArray and JSONObject. Which you can easily use to iterate through the data in your JSON request, and check what's in "element_type" and write to a file accordingly.
I need to implement a simple shell utility in Ruby which parses JSON from a file and return a particular field from it.
JSON examples to be parsed:
{"status": "fail", "messages": ["Out of capacity"]}
{"status": "success", "messages": [], "result": {"node": {"ip": "1.2.3.4", "description": "", "id": 974, "name": "VM#3"}}}
Idea is to create a CLI utility with two parameters: JSON file to read and field from JSON to extract:
./get_json_field.rb ~/tmp.XXXXXX 'result.node.ip'
./get_json_field.rb ~/tmp.XXXXXX 'messages.0'
I'm struggling how to map 2nd parameter to parsed JSON data structure in Ruby. I can write an iterator for sure, splitting string to an array using dot as separator an go through it item by item but this doesn't look like elegant solution.
Any suggestions for more elegant way?
There is nothing wrong with splitting string and going through parts of it:
require 'json'
data1 = JSON.load('{"status": "fail", "messages": ["Out of capacity"]}')
data2 = JSON.load('{"status": "success", "messages": [], "result": {"node": {"ip": "1.2.3.4", "description": "", "id": 974, "name": "VM#3"}}}')
def get_from_json(data, query)
query.split('.').inject(data) do |memo, key|
key = key.to_i if memo.is_a? Array
memo.fetch(key)
end
end
get_from_json(data1, 'messages.0') # => "Out of capacity"
get_from_json(data2, 'result.node.ip') # => "1.2.3.4"
Take a look at jq it might already do what you are looking for.
jq .messages[0]
jq .node.message.ip
See http://stedolan.github.com/jq/