I have a Python script that make an API call to retrieve data from Zendesk. (Using Python 3.x) The JSON object has a structure like this:
{
"id": 35436,
"url": "https://company.zendesk.com/api/v2/tickets/35436.json",
"external_id": "ahg35h3jh",
"created_at": "2009-07-20T22:55:29Z",
"updated_at": "2011-05-05T10:38:52Z",
"type": "incident",
"subject": "Help, my printer is on fire!",
"raw_subject": "{{dc.printer_on_fire}}",
"description": "The fire is very colorful.",
"priority": "high",
"status": "open",
"recipient": "support#company.com",
"requester_id": 20978392,
"submitter_id": 76872,
"assignee_id": 235323,
"organization_id": 509974,
"group_id": 98738,
"collaborator_ids": [35334, 234],
"forum_topic_id": 72648221,
"problem_id": 9873764,
"has_incidents": false,
"due_at": null,
"tags": ["enterprise", "other_tag"],
"via": {
"channel": "web"
},
"custom_fields": [
{
"id": 27642,
"value": "745"
},
{
"id": 27648,
"value": "yes"
}
],
"satisfaction_rating": {
"id": 1234,
"score": "good",
"comment": "Great support!"
},
"sharing_agreement_ids": [84432]
}
Where I am running into issues is in the "custom_fields" section specifically. I have a particular custom field inside of each ticket I need the value for, and I only want that particular value.
To spare you too many specifics of the Python code, I am reading through each value below for each ticket and adding it to an output variable before writing that output variable to a .csv. Here is the particular place the breakage is occuring:
output += str(ticket['custom_fields'][id:23825198]).replace(',', '')+','
All the replace nonsense is to make sure that since it is going into a comma delimited file, any commas inside of the values are removed. Anyway, here is the error I am getting:
output += str(ticket['custom_fields'][id:int(23825198)]).replace(',', '')+','
TypeError: slice indices must be integers or None or have an __index__ method
As you can see I have tried a couple different variations of this to try and resolve the issue, and have yet to find a fix. I could use some help!
Thanks...
Are you using json.loads()? If so you can then get the keys, and do an if statement against the keys. An example on how to get the keys and their respective values is shown below.
import json
some_json = """{
"id": 35436,
"url": "https://company.zendesk.com/api/v2/tickets/35436.json",
"external_id": "ahg35h3jh",
"created_at": "2009-07-20T22:55:29Z",
"updated_at": "2011-05-05T10:38:52Z",
"type": "incident",
"subject": "Help, my printer is on fire!",
"raw_subject": "{{dc.printer_on_fire}}",
"description": "The fire is very colorful.",
"priority": "high",
"status": "open",
"recipient": "support#company.com",
"requester_id": 20978392,
"submitter_id": 76872,
"assignee_id": 235323,
"organization_id": 509974,
"group_id": 98738,
"collaborator_ids": [35334, 234],
"forum_topic_id": 72648221,
"problem_id": 9873764,
"has_incidents": false,
"due_at": null,
"tags": ["enterprise", "other_tag"],
"via": {
"channel": "web"
},
"custom_fields": [
{
"sid": 27642,
"value": "745"
},
{
"id": 27648,
"value": "yes"
}
],
"satisfaction_rating": {
"id": 1234,
"score": "good",
"comment": "Great support!"
},
"sharing_agreement_ids": [84432]
}"""
# load the json object
zenJSONObj = json.loads(some_json)
# Shows a list of all custom fields
print("All the custom field data")
print(zenJSONObj['custom_fields'])
print("----")
# Tells you all the keys in the custom_fields
print("How keys and the values")
for custom_field in zenJSONObj['custom_fields']:
print("----")
for key in custom_field.keys():
print("key:",key," value: ",custom_field[key])
You can then modify the JSON object by doing something like
print(zenJSONObj['custom_fields'][0])
zenJSONObj['custom_fields'][0]['value'] = 'something new'
print(zenJSONObj['custom_fields'][0])
Then re-encode it using the following:
newJSONObject = json.dumps(zenJSONObj, sort_keys=True, indent=4)
I hope this is of some help.
Related
After running a GET API call, I am presented with the following output:
{
"limit": 1000,
"offset": 0,
"records": [{
"associatedItems": [{
"id": "rk:db",
"name": "rk:db",
"parentId": "10000",
"parentName": "com.atlassian.crowd.directory.IdentityPlatformRemoteDirectory",
"typeName": "USER"
}],
"category": "group management",
"created": "2022-10-13T17:44:01.633+0000",
"eventSource": "",
"id": 42914,
"objectItem": {
"name": "system-administrators",
"parentId": "10000",
"parentName": "com.atlassian.crowd.directory.IdentityPlatformRemoteDirectory",
"typeName": "GROUP"
},
"summary": "User added to group"
}, {
"associatedItems": [{
"id": "rk:da",
"name": "rk:da",
"parentId": "10000",
"parentName": "com.atlassian.crowd.directory.IdentityPlatformRemoteDirectory",
"typeName": "USER"
}],
"category": "group management",
"created": "2022-10-13T17:44:01.610+0000",
"eventSource": "",
"id": 42913,
"objectItem": {
"name": "site-admins",
"parentId": "10000",
"parentName": "com.atlassian.crowd.directory.IdentityPlatformRemoteDirectory",
"typeName": "GROUP"
}
}],
"total": 492
}
I want to extract each element from the "records" array to create multiple JSON objects.
One (1) JSON object per array element.
For example: JSON Object #1
{
"associatedItems": [{
"id": "rk:db",
"name": "rk:db",
"parentId": "10000",
"parentName": "com.atlassian.crowd.directory.IdentityPlatformRemoteDirectory",
"typeName": "USER"
}],
"category": "group management",
"created": "2022-10-13T17:44:01.633+0000",
"eventSource": "",
"id": 42914,
"objectItem": {
"name": "system-administrators",
"parentId": "10000",
"parentName": "com.atlassian.crowd.directory.IdentityPlatformRemoteDirectory",
"typeName": "GROUP"
},
"summary": "User added to group"
}
Ideally, I want to perform the JSON object manipulation using Python.
Can anyone help me achieve this goal? Thanks!
Not sure if this is "best practice". But I was able to convert the "records" array (nested inside of the GET api response) into a Python dictionary. I then used a FOR loop to convert each array element back into valid JSON.
jira_records = response.json()['records']
for record in jira_records:
x = json.dumps(record)
print(x)
The final result is 1 (valid) JSON object per array element--which is exactly what I needed.
If there is less roundabout way to accomplish this, I'de love to "learn more".
I have a python dictionary that looks something like this:
[
{
"timestamp": 1621559698154,
"user": {
"uri": "spotify:user:xxxxxxxxxxxxxxxxxxxx",
"name": "Panda",
"imageUrl": "https://i.scdn.co/image/ab67757000003b82b54c68ed19f1047912529ef4"
},
"track": {
"uri": "spotify:track:6SJSOont5dooK2IXQoolNQ",
"name": "Dirty",
"imageUrl": "http://i.scdn.co/image/ab67616d0000b273a36e3d46e406deebdd5eafb0",
"album": {
"uri": "spotify:album:0NMpswZbEcswI3OIe6ml3Y",
"name": "Dirty (Live)"
},
"artist": {
"uri": "spotify:artist:4ZgQDCtRqZlhLswVS6MHN4",
"name": "grandson"
},
"context": {
"uri": "spotify:artist:4ZgQDCtRqZlhLswVS6MHN4",
"name": "grandson",
"index": 0
}
}
},
{
"timestamp": 1621816159299,
"user": {
"uri": "spotify:user:xxxxxxxxxxxxxxxxxxxxxxxx",
"name": "maja",
"imageUrl": "https://i.scdn.co/image/ab67757000003b8286459151d5426f5a9e77cfee"
},
"track": {
"uri": "spotify:track:172rW45GEnGoJUuWfm1drt",
"name": "Your Best American Girl",
"imageUrl": "http://i.scdn.co/image/ab67616d0000b27351630f0f26aff5bbf9e10835",
"album": {
"uri": "spotify:album:16i5KnBjWgUtwOO7sVMnJB",
"name": "Puberty 2"
},
"artist": {
"uri": "spotify:artist:2uYWxilOVlUdk4oV9DvwqK",
"name": "Mitski"
},
"context": {
"uri": "spotify:playlist:0tol7yRYYfiPJ17BuJQKu2",
"name": "I Bet on Losing Dogs",
"index": 0
}
}
}
]
How can I get, for example, the group of values for user.name "Panda" and then get that specific "track" list? I can't parse through the list by index because the list order changes randomly.
If you are only looking for "Panda", then you can just loop over the list, check whether the name is "Panda", and then retrieve the track list accordingly.
Otherwise, that would be inefficient if you want to do that for many different users. I would first make a dict that maps user to its index in the list, and then use that for each user (I am assuming that the list does not get modified while you execute the code, although it can be modified between executions.)
user_to_id = {data[i]['user']['name']: i for i in range(len(data))} # {'Panda': 0, 'maja': 1}
def get_track(user):
return data[user_to_id[user]]['track']
print(get_track('maja'))
print(get_track('Panda'))
where data is the list you provided.
Or, perhaps just make a dictionary of tracks directly:
tracks = {item['user']['name']: item['track'] for item in data}
print(tracks['Panda'])
If you want to get list of tracks for user Panda:
tracks = [entry['track'] for entry in data if entry['user']['name'] == 'Panda']
I have this json file. It's a report of threat intelligence platform.
{
"data": {
"attributes": {
"authentihash": "a077f952798eb3bc0730c7c4774da7636326cf4b524ed6571b7eaf3d43f0bd9b",
"creation_date": 1387937380,
"crowdsourced_yara_results": [
{
"author": "Florian Roth",
"description": "Malware InstallRex / AntiFW",
"rule_name": "PUP_InstallRex_AntiFWb",
"ruleset_id": "000ca30c43",
"ruleset_name": "crime_antifw_installrex",
"source": "https://github.com/Neo23x0/signature-base"
}
],
"first_submission_date": 1389124248,
"last_analysis_date": 1603898773,
"last_analysis_results": {
"ALYac": {
"category": "undetected",
"engine_name": "ALYac",
"engine_update": "20201028",
"engine_version": "1.1.1.5",
"method": "blacklist",
"result": null
},
"APEX": {
"category": "undetected",
"engine_name": "APEX",
"engine_update": "20201028",
"engine_version": "6.90",
"method": "blacklist",
"result": null
},
"AVG": {
"category": "malicious",
"engine_name": "AVG",
"engine_update": "20201028",
"engine_version": "18.4.3895.0",
"method": "blacklist",
"result": "FileRepMetagen [Malware]"
},
I would count how many antimalware detected the malware as "maliciuous". So
i can access and print the whole list of "last_analysis_results", but i can't access to "category" of each antimalware.
I try with:
for elem in data['data']['attributes']['last_analysis_results']:
but then? thank you :)
Use .values() to get the dictionary values. Then you can access the category element of each dictionary.
sum(r['category'] == 'malicious' for r in data['data']['attributes']['last_analysis_results'].values())
Booleans are treated as 1 and 0 when used arithmetically, so summing the comparisons counts the number of times it's true.
When I try to add an attachment to my message I either only get the text or if I leave out the text I get "error": "no_text", is there any way to send an attachmet with chat.postMessage?
This is the python code I use for sending the message:
r = requests.post('https://slack.com/api/chat.postMessage', params=json.loads("""
{
"token": "xoxp-mytokenhere",
"channel": "C4mychannelhere",
"attachments": [
{
"text": "Question?",
"fallback": "Question?",
"callback_id": "callback_id",
"color": "#3AA3E3",
"attachment_type": "default",
"actions": [
{
"name": "question",
"text": "Yes",
"style": "good",
"type": "button",
"value": "yes"
},
{
"name": "question",
"text": "Nope",
"style": "good",
"type": "button",
"value": "no"
}
]
}
]
}
"""))
Based on the comment I went with the following solution:
r = requests.post('https://slack.com/api/chat.postMessage', params=json.loads({
"token": "xoxp-mytokenhere",
"channel": "C4mychannelhere",
"attachments": json.dumps([
{
"text": "Question?",
"fallback": "Question?",
"callback_id": "callback_id",
"color": "#3AA3E3",
"attachment_type": "default",
"actions": [
{
"name": "question",
"text": "Yes",
"style": "good",
"type": "button",
"value": "yes"
},
{
"name": "question",
"text": "Nope",
"style": "good",
"type": "button",
"value": "no"
}
]
}
])
}))
It looks like you're trying to send a JSON string as your entire set of parameters to chat.postMessage.
chat.postMessage and other web API methods only support URL-encoded query or POST body parameters, so your fields like token and channel and attachments are sent as application/x-www-form-urlencoded key/value pairs instead.
To complicate things a little further, the attachments parameter actually does take a string of URL-encoded JSON data. Your JSON array needs to be URL-encoded and stuffed into that parameter.
Depending on your goals, you could either skip using json.loads and just pass that JSON string as your attachments parameter and requests will take care of URL-encoding it for you -- or you can use something like json.dump on a native Python array you build with the same attributes.
I am using Django to receive and process push notifications from the foursquare real-time api. Each checkin is pushed as a POST request to my server containing a single parameter named checkin. I am trying to grab the value of the checkin parameter and convert it to a python dict. However, calling json.loads always results in the following error:
NameError: name 'true' is not defined
I know the json is valid, so I must be doing something wrong.
The code is:
import json
def push(request):
if request.is_secure():
checkin_json = request.POST['checkin']
checkin = json.load(request.POST)
The body of the post request is:
"checkin =
{
"id": "4e6fe1404b90c00032eeac34",
"createdAt": 1315955008,
"type": "checkin",
"timeZone": "America/New_York",
"user": {
"id": "1",
"firstName": "Jimmy",
"lastName": "Foursquare",
"photo": "https://foursquare.com/img/blank_boy.png",
"gender": "male",
"homeCity": "New York, NY",
"relationship": "self"
},
"venue": {
"id": "4ab7e57cf964a5205f7b20e3",
"name": "foursquare HQ",
"contact": {
"twitter": "foursquare"
},
"location": {
"address": "East Village",
"lat": 40.72809214560253,
"lng": -73.99112284183502,
"city": "New York",
"state": "NY",
"postalCode": "10003",
"country": "USA"
},
"categories": [
{
"id": "4bf58dd8d48988d125941735",
"name": "Tech Startup",
"pluralName": "Tech Startups",
"shortName": "Tech Startup",
"icon": "https://foursquare.com/img/categories/building/default.png",
"parents": [
"Professional & Other Places",
"Offices"
],
"primary": true
}
],
"verified": true,
"stats": {
"checkinsCount": 7313,
"usersCount": 565,
"tipCount": 128
},
"url": "http://foursquare.com"
}
}"
Try json.loads(checkin_json) instead of json.load(request.POST). Notice the extra 's'.
change checkin = json.load(request.POST) to checkin = json.loads(checkin_json)
On python, boolean values are Capitalized (first letter is uppercase): True/False.
Check this.
EDIT:
Pay attentiot at this lines:
"primary": true
}
],
"verified": true,
Both "true" values are lowercase and need to be capitalized