Forum Discussion

timhartley's avatar
timhartley
New Contributor
7 years ago

Using Collaborator JSON APIs from Python

I have a very simple Python 3.5 script to try and replicate a ServerInfoService.getVersion command that works in the JSON Testing page for Collaborator.


Extracts of the key bits of my script below:

# Server URL
url = "http://myserver.com/services/json/v1"

# Simple JSON API command to try
# [{"command" : "ServerInfoService.getVersion"}] # This is the command that works OK in the Collab JSON API webpage
val_get_version = {"command" : "ServerInfoService.getVersion"}

# The urllib.parse.urlencode() function takes a mapping or sequence of 2-tuples and returns a string in this format.
data = urllib.parse.urlencode(val_get_version)

# Add the [ and ] array delimiters that the JSON seems to require to the string... Do I need to do this ???
#cmd_data = data
cmd_data = "[" + data + "]"


# Encoded to bytes before being used as the data parameter in the request.
cmd_data = cmd_data.encode('utf-8')

# Make the request
req = urllib.request.Request(url, cmd_data)
response = urllib.request.urlopen(req)

 

When I run this:


The request is going to the server OK but no matter what I try for the request format I get the Response:


b'[{"errors":[{"code":"JsonMappingException","message":"No content to map due to end-of-input\\n at [Source: ; line: 1, column: 0]"}]}]'

 

It seems my formatting of the request is not recognised but I am stumped as to what I need to change/add to make this work.

I'm sadly not a Python expert but the basics I am using here I do already have working with other tool that support their own JSON APIs.

 

As an aside I am going this route as I want my reports to include the Subversion revision of the files in a Review.  It seems the standard reports nor the custom report nor the admin-xml can give me this (unless anyone can enlighten me otherwise).

 

Grateful for any hints or suggestions as I've disappointingly ground to a halt at the first hurdle!

 

Thanks 

3 Replies

  • Hi,

     

    Print the value of the cmd_data variable - it doesn't appear to be JSON:

    [command=ServerInfoService.getVersion]

     

    • timhartley's avatar
      timhartley
      New Contributor

      Thanks Alexey

       I've got something simple working now :)

      The problem was as you say with the format for the cmd_data, fixed now and basics working

      BR, Tim

       

  • timhartley's avatar
    timhartley
    New Contributor

    So with a little help from various sources, inc. the support team, to get me past my Python inadequacies I have something basic working to pull records out of the database via the JSON APIs.
    The initial problems was my duff formatting of the command and also the help of the json.dumps() function (should read this stuff before I try and use it!).

     

    Condensed extract below of the key bits.
    I can issue now successfully command posts and process responses to create 'custom' classes from them so I can add whatever methods I later want :smileyhappy:


    # Headers to specify the content type and encoding for the query
    headers = {'Content-Type': 'application/json;charset=utf-8'}


    # val_get_version = {"command" : "ServerInfoService.getVersion"}

    # json.dumps() returns $ and data must be a bytes object sto send to the server

    json_val_get_version = json.dumps([
    {
    u'command' : (u'ServerInfoService.getVersion')
    }
    ])


      
    # It should be encoded to bytes (UTF-8) before being used as the data parameter.
    cmd_data = json_val_get_version

     

    cmd_data.encode('utf-8')
    req = urllib.request.Request(url, cmd_data, headers=headers)
    response = urllib.request.urlopen(req)

     

    for record in response :

        # convert byte object record into string?
        record = record.decode('utf-8')

        obj = json.loads(record, object_hook = CCollab_Participants_from_json)

        # etc...

     

    The CCollab_Version_from_json) hook traverses the record structure (if it is nested) and creates the custom CCollab_Version class object for me to do as I wish with.


    I still have the hurdle of extracting JUST the Subversion revision from the ReviewSummary (I am not ware of it being available anywhere else but maybe I need to dig more).
    Currently for an all but empty Review this is ~15K characters and a level of nesting (and consequently traversing) that is a little off-putting...