Python JSON array left join update - python

I have a nested JSON array, and a separate second array.
Would like perform the equivalent of a SQL UPDATE using a left join.
In other words, keep all items from the main json, and where the same item (key='order') appears in the secondary one, update/append values in the main.
Can obviously achieve this by looping - but really looking for a more elegant & efficient solution.
Most examples of 'merging' json I've seen involve appending new items, or appending - very little regarding 'updating'.
Any pointers appreciated :)
Main JSON object with nested array 'steps'
{
"manifest_header": {
"name": "test",
},
"steps": [
{
"order": "100",
"value": "some value"
},
{
"order": "200",
"value": "some other value"
}
]
}
JSON Array with values to add
{
"steps": [
{
"order": "200",
"etag": "aaaaabbbbbccccddddeeeeefffffgggg"
}
]
}
Desired Result:
{
"manifest_header": {
"name": "test",
},
"steps": [
{
"order": "100",
"value": "some value"
},
{
"order": "200",
"value": "some other value",
"etag": "aaaaabbbbbccccddddeeeeefffffgggg"
}
]
}

Related

replace nested document array mongodb with python

i have this document in mongodb
{
"_id": {
"$oid": "62644af0368cb0a46d7c2a95"
},
"insertionData": "23/04/2022 19:50:50",
"ipfsMetadata": {
"Name": "data.json",
"Hash": "Qmb3FWgyJHzJA7WCBX1phgkV93GiEQ9UDWUYffDqUCbe7E",
"Size": "431"
},
"metadata": {
"sessionDate": "20220415 17:42:55",
"dataSender": "user345",
"data": {
"height": "180",
"weight": "80"
},
"addtionalInformation": [
{
"name": "poolsize",
"value": "30m"
},
{
"name": "swimStyle",
"value": "mariposa"
},
{
"name": "modality",
"value": "swim"
},
{
"name": "gender-title",
"value": "schoolA"
}
]
},
"fileId": {
"$numberLong": "4"
}
}
I want to update nested array document, for instance the name with gender-tittle. This have value schoolA and i want to change to adult like the body. I give the parameter number of fileId in the post request and in body i pass this
post request : localhost/sessionUpdate/4
and body:
{
"name": "gender-title",
"value": "adultos"
}
flask
#app.route('/sessionUpdate/<string:a>', methods=['PUT'])
def sessionUpdate(a):
datas=request.json
r=str(datas['name'])
r2=str(datas['value'])
print(r,r2)
r3=collection.update_one({'fileId':a, 'metadata.addtionalInformation':r}, {'$set':{'metadata.addtionalInformation.$.value':r2}})
return str(r3),200
i'm getting the 200 but the document don't update with the new value.
As you are using positional operator $ to work with your array, make sure your select query is targeting array element. You can see in below query that it is targeting metadata.addtionalInformation array with the condition that name: "gender-title"
db.collection.update({
"fileId": 4,
"metadata.addtionalInformation.name": "gender-title"
},
{
"$set": {
"metadata.addtionalInformation.$.value": "junior"
}
})
Here is the Mongo playground for your reference.

How to read JSON file with number of key in nested dictionary keeps changing

I have this JSON nested dictionary I need to parse into SQL table. The problem is the number of key tank (max is 4) in nested dictionary keeps changing with different site_id. Are there a way to read them?
{
"data": [
{
"site_id": 30183,
"city": "Seattle",
"state": "US-WA",
"tank": [
{
"id": 00001,
"name": "Diesel"
},
{
"id": 00002,
"name": "Diesel"
},
{
"id": 00003,
"name": "Unleaded 89"
}
]
},
{
"site_id": 200942,
"city": "Boise",
"state": "ID-WA",
"tank": [
{
"id": 00001,
"name": "Diesel"
},
{
"id": 00002,
"name": "Unleaded 95"
}
]
}
]
}
Here is my current code:
for site in response['data']:
row = []
row.extend([site['site_id'], site['city'], site['state']])
for tank in site['tank']:
row.extend([tank['id'], tank['name']])
Any site_id that does not have enough 4 tank can have missing value replaced with NULL
I don't know how to modify it to adjust to different number of tank keys. Any suggestion help! Thank you

python combine values for a specific key separated by comma

Is there a way to combine multiple values for a specific key separated by comma. In my case i am trying to print multiple service.names values so they can be printed in a single line separated by comma.
How can i combine the service.name values separated by comma so they print like below:
{
"number": 1,
"service name": "FTP-Server, SSH-Server"
}
I tried below in pyjq but it separates values by a complete separate block.
.group[].group[] | { "number": .number, "service name": .service[].name }
Here is the output i am getting
{
"number": 1,
"service name": "FTP-Server"
}
{
"number": 1,
"service name": "SSH-Server"
}
Given below same data with/without object-dictionary. I am ok with any format.
JSON file with object-dictionary enabled
{
"objects-dictionary": [
{
"name": "FTP-Server",
"port": "21",
"type": "service-tcp",
"uid": "ef245528-9a3d-11d6-9eaa-3e5a6fdd6a6a"
},
{
"name": "SSH-Server",
"port": "22",
"type": "service-tcp",
"uid": "dff4f7ba-9a3d-11d6-91c1-3e5a6fdd5151"
}
],
"base": [
{
"number": 1,
"service": [
"ef245528-9a3d-11d6-9eaa-3e5a6fdd6a6a",
"dff4f7ba-9a3d-11d6-91c1-3e5a6fdd5151"
],
"uid": "90088436-ac42-4363-84a6-3dbebf3c11f0"
}
]
}
JSON file without object-dictionary
{
"group": [
{
"group": [
{
"number": 1,
"service": [
{
"name": "FTP-Server",
"port": "21",
"type": "service-tcp",
"uid": "ef245528-9a3d-11d6-9eaa-3e5a6fdd6a6a"
},
{
"name": "SSH-Server",
"port": "22",
"type": "service-tcp",
"uid": "dff4f7ba-9a3d-11d6-91c1-3e5a6fdd5151"
}
],
"uid": "90088436-ac42-4363-84a6-3dbebf3c11f0"
}
]
}
]
}
It's rather unclear what you expect as output, but given your last example and using jq you can concatenate both service names together:
<file jq '[.group[].group[].service[].name] | join(",")'
Note that join expects an array, so the names need to be inside an array [ ... ].
If you need to add this string within the object itself, you might do something like:
<file jq '.service.name=([.group[].group[].service[].name] | join(","))'
With your second JSON text, the following filter:
.group[].group[]
| { "number": .number, "service name": ([.service[].name]|join(", ")) }
produces the output that you've indicated you expected (including the space after the comma):
{
"number": 1,
"service name": "FTP-Server, SSH-Server"
}

Generating json file from text file in Python and removing unnecessary braces

Basically I'm generating a json Terraform file from a text file, but I can't get it to format in the correct way:
I want the finished Terraform file to look like this:
{
"resource": {
"aws_route53_record": {
"analytics": {
"name": "analytics",
"records": ["1.2.3.4"],
"ttl": "1800",
"type": "A"
},
"analytics-test": {
"name": "analytics-test",
"records": ["1.2.3.4"],
"ttl": "300",
"type": "A"
}
}
}
}
which is the format Terraform requires to parse json.
So I load the text file in Python, and iterate over each line producing a list of lists that look like so:
records = [["analytics", "1.2.3.4", "1800", "A"],["analytics-test", "1.2.3.4", "300", "A"]]
My code to generate the file at the moment looks like this
I create a dict placeholder containing top level variable like so:
json_object = {'resource': {'aws_route53_record': None}}
Then I look through records and assign the appropriate values:
for each_list in data:
terrarecord = {
each_list[0]:{
"name": each_list[0],
"type": each_list[2],
"ttl": each_list[1],
"records": [each_list[3].replace('\n', '')]
}
}
record_holder.append(terrarecord)
The record_holder object is an empty list that I then use to fill in the json_objects like so:
json_object['resource']['aws_route53_record'] = record_holder
What this gives me in the finished file is:
{
"resource": {
"aws_route53_record": [{
"analytics": {
"ttl": "1800",
"records": ["173.194.245.129"],
"name": "analytics",
"type": "A"
}
}, {
"analytics-test": {
"ttl": "300",
"records": ["130.211.89.168"],
"name": "analytics-test",
"type": "A"
}
}]
}
}
So would there be an easier way to do this without adding the extra [] and {}s that my little loop does?
Why are you creating the intermediate list when you want the dictionary?
terrarecord = {}
for each_list in data:
terrarecord[each_list[0]] = {
"name": each_list[0],
"type": each_list[2],
"ttl": each_list[1],
"records": [each_list[3].replace('\n', '')]
}
}
json_object['resource']['aws_route53_record'] = terrarecord

Unable to pull data from json using python

I have the following json
{
"response": {
"message": null,
"exception": null,
"context": [
{
"headers": null,
"name": "aname",
"children": [
{
"type": "cluster-connectivity",
"name": "cluster-connectivity"
},
{
"type": "consistency-groups",
"name": "consistency-groups"
},
{
"type": "devices",
"name": "devices"
},
{
"type": "exports",
"name": "exports"
},
{
"type": "storage-elements",
"name": "storage-elements"
},
{
"type": "system-volumes",
"name": "system-volumes"
},
{
"type": "uninterruptible-power-supplies",
"name": "uninterruptible-power-supplies"
},
{
"type": "virtual-volumes",
"name": "virtual-volumes"
}
],
"parent": "/clusters",
"attributes": [
{
"value": "true",
"name": "allow-auto-join"
},
{
"value": "0",
"name": "auto-expel-count"
},
{
"value": "0",
"name": "auto-expel-period"
},
{
"value": "0",
"name": "auto-join-delay"
},
{
"value": "1",
"name": "cluster-id"
},
{
"value": "true",
"name": "connected"
},
{
"value": "synchronous",
"name": "default-cache-mode"
},
{
"value": "true",
"name": "default-caw-template"
},
{
"value": "blah",
"name": "default-director"
},
{
"value": [
"blah",
"blah"
],
"name": "director-names"
},
{
"value": [
],
"name": "health-indications"
},
{
"value": "ok",
"name": "health-state"
},
{
"value": "1",
"name": "island-id"
},
{
"value": "blah",
"name": "name"
},
{
"value": "ok",
"name": "operational-status"
},
{
"value": [
],
"name": "transition-indications"
},
{
"value": [
],
"name": "transition-progress"
}
],
"type": "cluster"
}
],
"custom-data": null
}
}
which im trying to parse using the json module in python. I am only intrested in getting the following information out of it.
Name Value
operational-status Value
health-state Value
Here is what i have tried.
in the below script data is the json returned from a webpage
json = json.loads(data)
healthstate= json['response']['context']['operational-status']
operationalstatus = json['response']['context']['health-status']
Unfortunately i think i must be missing something as the above results in an error that indexes must be integers not string.
if I try
healthstate= json['response'][0]
it errors saying index 0 is out of range.
Any help would be gratefully received.
json['response']['context'] is a list, so that object requires you to use integer indices.
Each item in that list is itself a dictionary again. In this case there is only one such item.
To get all "name": "health-state" dictionaries out of that structure you'd need to do a little more processing:
[attr['value'] for attr in json['response']['context'][0]['attributes'] if attr['name'] == 'health-state']
would give you a list of of matching values for health-state in the first context.
Demo:
>>> [attr['value'] for attr in json['response']['context'][0]['attributes'] if attr['name'] == 'health-state']
[u'ok']
You have to follow the data structure. It's best to interactively manipulate the data and check what every item is. If it's a list you'll have to index it positionally or iterate through it and check the values. If it's a dict you'll have to index it by it's keys. For example here is a function that get's the context and then iterates through it's attributes checking for a particular name.
def get_attribute(data, attribute):
for attrib in data['response']['context'][0]['attributes']:
if attrib['name'] == attribute:
return attrib['value']
return 'Not Found'
>>> data = json.loads(s)
>>> get_attribute(data, 'operational-status')
u'ok'
>>> get_attribute(data, 'health-state')
u'ok'
json['reponse']['context'] is a list, not a dict. The structure is not exactly what you think it is.
For example, the only "operational status" I see in there can be read with the following:
json['response']['context'][0]['attributes'][0]['operational-status']

Categories