Parse JSON from CURL output using python - python

I am trying to get value of id i.e. "id": 59 which is in the curl output in form of json.
Below is the curl output in json:
[{"id":59,"description":"This is a demo project","name":"Demo_Project","name_with_namespace":"sam / Demo_Project","path":"demo_project","path_with_namespace":"sam/demo_project","created_at":"2020-03-02T08:43:13.664Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"ssh://git#od-test.od.com:2222/sam/demo_project.git","http_url_to_repo":"https://od-test.od.com/gitlab/sam/demo_project.git","web_url":"https://od-test.od.com/gitlab/sam/demo_project","readme_url":"https://od-test.od.com/gitlab/sam/demo_project/blob/master/README.md","avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-04-09T09:28:09.860Z","namespace":{"id":2259,"name":"sam","path":"sam","kind":"user","full_path":"sam","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/755db8ssqaq50dcc9d189c53523b?s=80\u0026d=identicon","web_url":"https://od-test.od.com/gitlab/sam"}}]
I am using python to parse the json and get the value of id.
I have tried the following command to do the same but got an error.
curl --header "PRIVATE-TOKEN: 9999ayayayar66" "https://od-test.od.com/gitlab/api/v4/search?scope=projects&search=demo_project" | python -c 'import sys, json; print(json.load(sys.stdin)["id"])'
Error:
Can anyone help me the correct python command to get the value of id.
Thanks in advance.

The JSON contains an array of objects but you are treating it like it is a single object:
import sys, json; print(json.load(sys.stdin)["id"])
You're basically saying "here is a collection of objects, give me the ID of the object". It doesn't make sense.
If you assume you only ever want the ID of the first object in the array, you can use this:
import sys, json; print(json.load(sys.stdin)[0]["id"])

The root of you JSON object is actually an array, so you should get the first item out of it first:
curl --header "PRIVATE-TOKEN: 9999ayayayar66" "https://od-test.od.com/gitlab/api/v4/search?scope=projects&search=demo_project" | python -c 'import sys, json; print(json.load(sys.stdin)[0]["id"])'

You have to write print(json.load(sys.stdin)[0]["id"]) because json response is a list of dictionaries, not a dictionary.

Since you also tagged Python Requests, your CURL command could be translated to:
import requests
headers = {
'PRIVATE-TOKEN': '9999ayayayar66',
}
params = (
('scope', 'projects'),
('search', 'demo_project'),
)
response = requests.get('https://od-test.od.com/gitlab/api/v4/search', headers=headers, params=params)
Then you can get the id value from the JSON Response Content with response.json()[0]["id"]. This uses the built-in JSON decoder to convert the JSON response to a list of dictionaries.

Related

type error while parsing json output python

i'm trying to parse some fields of a json, that is an output for a command line. but i can't access to any field, i've always this error :
TypeError: 'int' object has no attribute '__getitem__'
my json output is like this :
{"result":"success","totalresults":"1","startnumber":0,"numreturned":1,"tickets":{
"ticket":[
{
"id":"2440",
"tid":"473970",
"deptid":"1",
"userid":"0",
"name":"John",
"email":"email#email.it",
"cc":"","c":"P1gqiLym",
"date":"2016-07-01 13:00:02",
"subject":"test",
"status":"stato",
"priority":"Medium",
"admin":"",
"attachment":"image001.jpg",
"lastreply":"",
"flag":"0",
"service":""
}
]
}
}
and my code is this :
import json
import sys
import subprocess
output=subprocess.call('pywhmcs --url http://whmcs.test.it --username myuser --password mypass --action gettickets --params status="tickets" email="email#email.com"',shell=True)
values = json.loads(str(output))
print (values['result'])
why i can't access to any fields? maybe i cannot parse this type of subprocess output?
thanks guys
The problem is that subprocess.call returns the resultcode of the execution; which is either 0 (if successful) or any other positive integer if there is an error condition.
Now, when you execute output['result'], it is the same as doing 0['result'] which doesn't make sense as numbers don't support fetching by [], the technical term for that is __getitem__.
You need to execute subprocess.check_output; which returns the output as a string.
Then you have another minor issue that you need to fetch the dictionary on the resulting parsed json, and not output.
In short, you need:
import json
# import sys -- not required
import subprocess
output=subprocess.check_output('pywhmcs --url http://whmcs.test.it --username myuser --password mypass --action gettickets --params status="tickets" email="email#email.com"',shell=True)
values = json.loads(str(output))
print (values['result']) # note values, not output

Python requests module - POST failing - invalid character 'o'

I am trying to convert a raw curl command to use Python Request Module with no luck. This is a simple request to query JBoss Mgmt interface but it does not parse my JSON correctly.
16:34:26,868 DEBUG [org.jboss.as.domain.http.api] (HttpManagementService-threads - 15) Unable to construct ModelNode 'Invalid character: o'
Python version
Python 2.7.6
Working raw cURL command:
/usr/bin/curl --digest -v -L -D - 'http://brenn:!12rori#localhost:9990/management' --header Content-Type:application/json '-d {"operation":"read-attribute","name":"server-state","json.pretty":1}'
In python code i read in my REST/cURL payload like so
import requests
----
def readconfigfile():
with open('jboss_modification.cfg') as f:
lines = f.readlines()
return lines
The config file looks like so
{"operation":"read-attribute","name":"server-state","json.pretty":1}
I convert the str format from readconfigfile() to a dictionary as follows
def converttodictionary(incominglines):
commands = []
for lin in incominglines:
#dumps = json.dumps(lin)
obj = json.loads(lin)
commands.append(obj)
return commands
The python code to execute this request is as follows
def applyconfig(lines):
url="http://localhost:9990/management"
auth=HTTPBasicAuth('brenn', '!12rori')
s = requests.Session()
re=s.get(url, auth=HTTPDigestAuth('brenn', '!12rori')) ##200 RESP
s.headers.update({'Content-Type': 'application/json'})
for line in lines:
payload=line
r=s.post(url,payload)
print(r.text)
Any help much appreciated?
Note: This question has been updated a few times as I resolved other issues....
The issues was...
Initial JSON requestfailed because when i read it from file python interpreted as a str.
Converted to dictionary using json.loads and server accepted request but could not parse the JSON with illegal character error
Converted this json back to a str using json.dumps -- which to my mind looks like what i was trying to do in the first place -- and this now works
read JSON file as per def readconfigfile(): above
convert to json/dictionary as per def converttodictionary above: json.loads(lin)
Convert this json "back" to a string using json.dumps and POST as follows
payload = json.dumps(command)
r = session.post(url, payload,auth=HTTPDigestAuth('brenn', '!12rori')
)

Writing Python equivalent of Perl code

I don't know a single thing of perl but from a big perl script, I managed to get the relevant parts and make a HTTP request. So, this perl code works perfectly.
#!/usr/bin/perl -w
use strict;
use LWP::UserAgent;
use HTTP::Request::Common;
my $ua = new LWP::UserAgent;
my $request = "X-CTCH-PVer: 0000001\r\n";
my $method_url = "http://localhost:8088/ctasd/GetStatus";
my $response = $ua->request (POST $method_url,Content => $request);
my $data = $response->status_line . "\n";
print $data;
print $response->content;
The above code outputs:
200 OK
X-CTCH-PVer: 0000001
From my understanding, it's doing a POST to a URL with the specified data. With that base, my python code looks like:
#!/usr/bin/python
import urllib
url = "http://localhost:8088/ctasd/GetStatus"
data = urllib.urlencode([("X-CTCH-PVer", "0000001")])
print urllib.urlopen(url, data).read()
But, this returns response as:
X-CTCH-Error: Missing protocol header "X-CTCH-PVer"
Please help me in making a Python equivalent of perl code.
So, the actual thing was, the $request in Perl was literally been sent as POST data without any change. Now I get why is the name content in Perl.
#!/usr/bin/python
import urllib
url = "http://localhost:8088/ctasd/GetStatus"
print urllib.urlopen(url, "X-CTCH-PVer: 0000001").read()
Worked. I actually found out about this after capturing the traffic in both cases and analysing it in wireshark.
The error is because you are not sending the header, you are making/sending a urlencoded string, hence the function urllib.urlencode
Try setting the request with actual headers:
#!/usr/bin/python
import urllib2
request = urllib2.Request("http://localhost:8088/ctasd/GetStatus", headers={"X-CTCH-PVer" : "0000001"})
contents = urllib2.urlopen(request).read()

Using curl with --data-urlencode and fetching the content in django

I have a file, and I need to send its contents to a function. What I am currently doing is as follows:
$ curl --data-urlencode "$( cat my_file.xml)" MyIP
# in function
def receiver(request):
print request.POST
This returns something like:
<QueryDict: {u'\ufeff<?xml version ': [u' "1.0" encoding = "UTF-8"?>\n<Orders>\n ...</Orders>']}>
In other words, the curl command is correctly sending the data to the django function; however, it is not easily retrievable since the POST data is split up between the request.POST key (`u'\ufeff
In addition the xml file is not properly url-encoded, so I don't think I can use curl -d #file.
It seems to be taking '\ufeff<?xml version ' as the QueryDict key. How would I pass the file contents here and retrieve it as a single string so I can parse the xml?
There is a very easy (hack) solution for this, use string concatenation on the request.POST dict to re-combine the information:
contents = request.POST.keys()[0] + "=" + request.POST.values()[0]

Reading a JSON array from file without modifications to the source in python

Stupid question, but takes a long time to figure out. I'm trying to post an API request to parse.com using python. The json array file is meant to be read by item and transferred. The problem is that whenever I do json.load(datafile) the text format is changed to the one that is not acceptable by the server. In particular instead of having {"field":"value"} I have now {u'field:'value'} which gives a server error. It must be some simple encoding problem, just having hard time figuring out.
Many thanks!
#! /usr/bin/env python
import os
import json
APPLICATION_ID="XXXXXXXXXXXXXXXXXXXX"
REST_API_KEY="XXXXXXXXXXXXXXXXXXXXXX"
File_to_Post="../Data/area.json"
command="cat %s" % (File_to_Post)
# Parse the JSON
fileh = open(File_to_Post)
objs = json.load(fileh)
for o in objs:
command1 = 'curl -X POST \
-H "X-Parse-Application-Id: %s" \
-H "X-Parse-REST-API-Key: %s" \
-H "Content-Type: application/json" \
-d "%s" \
https://api.parse.com/1/classes/Areaobject' % (APPLICATION_ID, REST_API_KEY, o)
os.system(command1)
fileh.close()
When you load it, the JSON becomes a Python object. If you want to turn it back into JSON then you need to use json.dump() or json.dumps().

Categories