Python 2.x Request Json

Pour mon projet PixUP, relativement aux hébergeurs d’images que sont framapic, et lutim - le premier utilisant sur ses serveurs le second - la réponse à ma requête d’envoi se fait par défaut au format JSON.

$ python --version
Python 2.7.11+

Pour la transmission de la requête, j’utilise donc ‘requests’ - c’est assez bien documenté, et assez facile à utiliser …

Le format JSON est vraiment restitué selon la documentation API officielle de Lutim … c’est l’usage typique du format API de l’ajout d’image qui est utilisé ; le retour étant bel et bien de ce type :

{
“success”: true,
“msg”: {
“real_short”: “abc”,
“short”: “abc/def”,
“token”: “ghijkl”,
“thumb”: XXX,
“filename”: “myimage.png”
}
}

parameter | type | role
success | true/false | upload-status
msg | dict
real_short | string | image identifier
short | string | real_short + encryption key
token | string
thumb | string | base64 encoded thumbnail of the image, if PerlMagick is installed on the server
filename | string | filename of the uploaded image

On réalise selon ce schéma que ‘msg’ est un dict, et que - pour l’exemple - ‘filename’ est une chaîne de caractère, n’est-ce pas ?!

Le code python qui gère la requête d’envoi d’ajout d’image est celui-ci, même si je ne fournis pas l’ensemble … :

              if scheme == 'https':

                if self.service == 'framapic' or self.service == 'lutim':

                    request = requests.post(self.actions[self.service]['url'],
                        files = info, data = datas, verify = False)

                else:
                    request = requests.post(self.actions[self.service]['url'],
                        files = info, data = datas, verify = True)

            elif scheme == 'http':

                request = requests.post(self.actions[self.service]['url'],
                    files = info, data = datas, verify = False)

            self.log.debug(request)
            del(scheme)

            request.encoding = 'utf-8'
            ctype = request.headers['Content-Type']   

            if ctype == 'application/json':
                self.response = request.json()
            else:
                self.response = request.text

Dans le cas de lutim - et assimilé - je passe donc par le traitement json, soit l’usage de request.json() affecté à la variable ‘self.response’ …

Il m’avait semblait comprendre que, puisque c’est un traitement json, je pouvais l’interroger, tel que - , par exemple, pour avoir le contenu de l’index ‘filename’ faisant partie du dictionnaire ‘msg’ :

self.response['msg']['filename']

Or, python me répond :

pprint(self.response['mssg']['filename'])
TypeError: string indices must be integers

J’ai essayé sous ces autres formes :

  • self.response[u'msg']['filename']
  • self.response[u'msg'][u'filename']
  • self.response[u'msg'][0]['filename']

Mais j’ai toujours le même message d’erreur … et, je ne comprends pas pourquoi il me dit que ce doit être un entier alors que clairement on a affaire à un index|key associatif …

Une idée ?

Tu as dû mal interpréter le type des variables quelque part. Clairement ici, tu t’attends à un dictionnaire et l’interpréteur te répond que self.response est de type string, et que ce type peut être indexé uniquement par des entiers (normal) ;-).

Ecoute, voici ce que restitue Lutim au format JSON :

{"msg":{"del_at_view":false,"thumb":"data:image\/jpeg;base64,\/9j\/4AAQSkZJRgABAQEASABIAAD\/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEP\nERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7\/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4e\nHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7\/wAARCABVADMDASIA\nAhEBAxEB\/8QAHQABAAICAgMAAAAAAAAAAAAAAAcIBAUDBgECCf\/EADQQAAEDAwIDBAkEAwEAAAAA\nAAECAwQABREGIQcSMRMiQdEIFDJCUXGBkqEWI2GTJmJjkf\/EABoBAAIDAQEAAAAAAAAAAAAAAAAB\nAgMFBgT\/xAAuEQABBAAFAwEGBwAAAAAAAAABAAIDEQQFITFBEmGRURMUIoHB0RUyUnGx8PH\/2gAM\nAwEAAhEDEQA\/AKZUpXPAjLmTmIja20LfcS2lTiwlCSogAqJ2A33NBNaoXBSsq7QJdqucm2zmVMyo\nzqmnUHwUDg1i0gQRYQlK2EmzzY1iiXl9KERZjrjcfKxzr5Mcygnry5OM9MgjwrX0BwdshKUpTQle\nzSFuOJbbQpa1EJSlIyST0AFetSX6ONmZunENEqQ2Ft21hUpIPTtMhKP\/AAqz9KoxU4w8LpTwLQpg\n0xwct9+t1qvHEFt1d3TDSzIYjv8AIHAnZtTqgMlwIwk4ONutba98COHU+IpqHCl2t7HdejylKx80\nrJB\/FTrYI2nYGkHrtqCKh9sRlyn3u8VNNpSVd0A9QB4bk11Dh5P0xre43Bqz6iDrEMpVyoSC72aw\nFJJ3xtzAHwzkdQa5R+Dzb4Hxv31oGg3mtdOe\/oo6qoPH\/Tt5sGqWWpbDaLQhhMe1FkktpZQPZOff\nySpWepUTUbVcz0o9L\/4Zd4a3G5SoLSJsZ4JwSEnc48DylYNUzreyid8kBZIKcw0fv87+vKYSlKVq\nJryBk4FWk9GbRTti0\/cJl7bMO4XgN+qpdGCyhBJAX4p5+b6YTnqajHgp+hrDbpGsNUz4z06O8W4U\nEjtFpIAPadn7ysnCSe6ME5zjFnOCN3iaxftd\/Qw4iO52j4bdUFKBQopHNjbqAa5zNcTNM8YWNvwk\nhpJ2PYfzfZIrvb1t1TatJIakW5hxnsiHF9oFFls5ylxB67HqCcA79K1\/DKzWdt96Dp6xQrLPKEh9\n1tsltTSSSAfEYJ2AOMkmpKXNC0FC+8lQwQfEViW1uJbi4YrSWy57RArR\/D3iWNzZTTRVev8Aeeya\njTXlgeYmXBvUy2pLEqO4wylo4D6VoKNh1SEhWTnxwN81RLiFo67aMvi4FwZUWFkmLJA7j6M7EH4\/\nEdQa+jvEwNztMLcUAXIy0uIPiN8K\/B\/FVt1bqXQ16udx4f6ofRHWjk5XJOEoC1ICgptz3Fjm97AP\nTfpWQZZstxrmtBexw6jyd6J+W37KOyqfSsm4x241wkxmn0PttOrbS6j2VgEgKH8HrSuoBsWpLGq0\nvoVamWY0+xOx5Thh8zzC22VLTyLI5kkpBwQoZA8eY\/Cq4\/pu8gEmIMD\/AKo86tRwg4uaO0NoWDYI\nwfirQgLf7OKslbhA5iogd45zvvWRmWMaxjSxvWQb01qv9pR6gVOzWpIK5Jjl0tvDq24koUPoQDWV\nJu8aO0XXXkpR8ScCoO1fxo0nf1R1KkSUuM5w4YjnNv4Zx0HWutxeLFkngi5CfFS0cIS6wVBz\/buZ\n\/ODvVEWcTOhe90R6hVDa7+3O+idhTxqPUMWRpie+01MkR22VKWpiM45kDchOBua+eesLu\/ftUXK8\nSEFtyXIU4UH3BnZP0AA+lXVY9IrSzTKG0SZjSUJCUoRFcASB4DAqtPHd63ay147f9LweVMpsKlHk\nDIU7k74VjcjBJ8TUcDmDpsR1TRlpqrIoDW+Tz9ErCiqlbY6du4ODFH9qPOlbfvEX6h5R1N9VOHCU\n2VOtYy7zydxSVRUuJ5m1PBYwFDoRjOxwM4+Vdw4z3KzzbtGjxYMBT62\/WX5MdlCCR2a0JRyp+QV1\n32+dVqGrrmDkNxuufZPnXKNbXcYyiMrACRzJJwBsB16Cs0YWdsJjDR5VQY4NpTfJZ0m2w6uNFbeW\nypXYoExZ9ZT3Akr7oKFbrJSMdMfPjej6bbQ7hhlxKHx2K0yFKcdRz7haAO6OXPeGDkD41DSde3pP\nRqJ9h868q1\/elDBah\/1nzqg4HEE30N8o9m5S7PZ0rySFMJ5ctBSf31Atq7IHCElOV5c7pCiCkb\/z\nWvvjdgTClepJYS4mQRFW3MU6t1vnUP3EEYQAnBByM7bb7RavXF3V1aifYfOuFesLorq3G+w+dWDB\nTV+RvlIxuXcHPbNK6UdUXInJRH+w+dKiMum7eUvZOWipSlbq9KUpShCUpShCUpShC\/\/Z\n","short":"YsqxRK8XjM\/kcIHocOnJUHKmyFU","real_short":"YsqxRK8XjM","created_at":1463477574,"filename":"CAByd.jpg","limit":"1","token":"VgJ5fRmTrFiTz0EzNvKV2df2","ext":"jpg"},"success":true}

Pour afficher son contenu, j’ai simplement fait une redirection log.debug, telle que :

 self.log.debug('URLs Response: %s' % self.response)

Donc, dans ma sortie log.debug, il s’affiche comme une ‘string’ ce qui est normal !

Mais selon la documentation API, c’est bien un dictionnaire - ou, alors j’ai mal compris ?!


Ahhh, je crois que j’ai trouvé - j’ai fait un log.debug sur la variable ‘ctype’ à laquelle est affecté le contenu de ‘request.headers[‘Content-Type’]’ - qui m’affiche le type de contenu retourné … tel que :

self.log.debug('Request Headers: ' + ctype)

Or, au lieu d’avoir juste la chaîne de caractère suivante ‘application/json’, il m’est retourné ‘application/json;charset=UTF-8’ - comme je fais une comparaison où je demande d’utiliser ‘requests.json()’ si ctype == ‘application/json’ sinon retourne ‘request.text’ … j’ai donc du texte retourné, donc une string !!!

Donc, il faut je m’y prenne différemment … à savoir, vérifier que dans le contenu de la variable ctype existe la chaîne suivante ‘application/json’, alors ‘request.json()’ sinon ‘request.text’ :wink:

Merci de m’avoir titillé @seb-ksl