JSONArray et liste python : comment manipuler ces deux types
toyo -
Bonjour,
J'ai écrit un script python qui permet de récupérer et transférer des données au format JSON.
Pour étudier mon problème, je vais partager uniquement deux de mes fonctions.
La première :
def create_cts(nwd, idd):
headers = {
'Authorization': 'Bearer xxx',
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json;charset=utf-8',
}
obs = search_obs(idd)
# we check that the obs are not empty
if obs != "[]":
# removal of unwanted chevrons at the beginning and end
json_data = obs[1:-1]
obj_python = json.loads(json_data)
response = requests.post(f'http://xxx/api/case/{nwd}/artifact', headers=headers, json=obj_python)
if response.status_code != 201 and response.status_code != 200:
print('ko: {}/{}'.format(response.status_code, response.text))
sys.exit(0)
Elle permet d'envoyer des données à un serveur, au format json.
Les deux paramètres sont des entiers qui aident à gérer les types de données concernées.
La fonction fait appel à celle-ci :
def search_obs(cid):
# Call the API
response = api_i.get_case_obs(caseId, query={}, sort=['-stte', '+ioc'], range='all')
if response.status_code == 200 or response.status_code == 201:
# Get response data
list = json.dumps(response.json())
return list
else:
print('Failure: {}/{}'.format(response.status_code, response.text))
Elle prend en paramètre un entier et retourne une liste contenant les données au format JSONArray.
Cependant, elle retourne un str et non JSONArray.
Dans le cas où la liste récupérée est dans ce format :
[
{
"_id": "~81940632",
"id": "~81940632",
"createdBy": "xxxxx",
"createdAt": 1672847636169,
"_type": "case_artifact",
"dataType": "ip",
"data": "xxxxxxxx",
"startDate": 1672847636169,
"tlp": 2,
"tags": ["ip"],
"ioc": false,
"sighted": false,
"message": "nonne",
"reports": {},
"stats": {},
"ignoreSimilarity": false
}
]
Cela fonctionne sans erreur, par contre, lorsqu'il y a plusieurs objets JSON, comme ceci :
[
{"_id": "~81940632",
"id": "~81940632",
"createdBy": "xxxx",
"createdAt": 1672847636169,
"_type": "case_artifact",
"dataType": "ip",
"data": "xxxx",
"startDate": 1672847636169,
"tlp": 2,
"tags": ["ip"],
"ioc": false,
"sighted": false,
"message": "nonne",
"reports": {},
"stats": {},
"ignoreSimilarity": false},
{
"_id": "~196840",
"id": "~196840",
"createdBy": "xxxx",
"updatedBy": "xxxxx",
"createdAt": 1672741863059,
"updatedAt": 1672843716872,
"_type": "case_artifact",
"dataType": "domain",
"data": "***@***",
"startDate": 1672741863059,
"tlp": 2,
"tags": ["domai"],
"ioc": true,
"sighted": false,
"message": "",
"reports": {},
"stats": {},
"ignoreSimilarity": false
}
]
Voici l'erreur :
json.decoder.JSONDecodeError: Extra data: line 1 column 332 (char 331)
J'ai cherché un peu comment faire, l'idée serait de faire un "for" sur le JSONArray mais le problème c'est que je récupère toujours la liste en "str" ou en liste (après modification du code).
J'ai aussi essayé de retourner directement le "json.dumps" pour avoir le type JSON, mais cela ne fonctionne pas.
- JSONArray et liste python : comment manipuler ces deux types
- Liste déroulante excel - Guide
- Liste code ascii - Guide
- Liste déroulante en cascade - Guide
- Citizen code python avis - Accueil - Outils
- Site dangereux liste - Guide
3 réponses
Bonsoir, ce qui est étonnant dans ton json est qu'il y a des true et false, et à mon avis c'est ce qui fait que ça foire, en python c'est True et non true qui devrait alors être un string et donc devrait être quoté, enfin je vois que ça, tente de remplacer true par True, idem pour false.
Et si ça foire encore, essaie ce qui indiqué dans ce post :
https://stackoverflow.com/questions/48140858/json-decoder-jsondecodeerror-extra-data-line-2-column-1-char-190#answer-64515116
Ok, en fait le problème c'est que je fais :
json_data = obs[1:-1]
Avant de faire json.loads, donc il ne comprend plus le JSON. Mais, le problème est que je suis obligée de supprimer ces crochets de début et de fin pour la requête, sinon il me créé une autre erreur.
Alors là je ne sais vraiment pas comment faire, car je reçois un JSON array du type [{},{}] que je mets dans un string et auquel je dois garder les crochets pour le "json.loads" mais ensuite les supprimer ... Cependant, une fois que je fais :
obj_python = json.loads(json_data)
Je ne peux plus supprimer les crochets, car cela devient une liste. (Ou alors je ne sais pas comment faire)
La requête POST, avec le paramètre JSON, doit ajouter automatiquement les crochets, c'est probablement pour ça que ça me créé une erreur. Je vais donc chercher comment envoyer des données brutes
Je n'arrive pas à reproduire ton bug, ni même ton problème avec ton json.
Un simple server lancé rapidos.
python3 -m http.server 8080
Puis dans un interpétreur, je récupère ton json.
guili@maman:~$ python3.7
Python 3.7.3 (default, Oct 31 2022, 14:04:00)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import json
>>> import requests
>>> response = requests.get('http://localhost:8080/list.json')
>>> response.status_code
200
>>> type(response.json())
<class 'list'>
>>> json.dumps(response.json())
'[{"_id": "~81940632", "id": "~81940632", "createdBy": "xxxx", "createdAt": 1672847636169, "_type": "case_artifact", "dataType": "ip", "data": "xxxx", "startDate": 1672847636169, "tlp": 2, "tags": ["ip"], "ioc": false, "sighted": false, "message": "nonne", "reports": {}, "stats": {}, "ignoreSimilarity": false}, {"_id": "~196840", "id": "~196840", "createdBy": "xxxx", "updatedBy": "xxxxx", "createdAt": 1672741863059, "updatedAt": 1672843716872, "_type": "case_artifact", "dataType": "domain", "data": "***@***", "startDate": 1672741863059, "tlp": 2, "tags": ["domai"], "ioc": true, "sighted": false, "message": "", "reports": {}, "stats": {}, "ignoreSimilarity": false}]'
>>>
>>>
>>> type(response.text)
<class 'str'>
>>> json.loads(response.text)
[{'_id': '~81940632', 'id': '~81940632', 'createdBy': 'xxxx', 'createdAt': 1672847636169, '_type': 'case_artifact', 'dataType': 'ip', 'data': 'xxxx', 'startDate': 1672847636169, 'tlp': 2, 'tags': ['ip'], 'ioc': False, 'sighted': False, 'message': 'nonne', 'reports': {}, 'stats': {}, 'ignoreSimilarity': False}, {'_id': '~196840', 'id': '~196840', 'createdBy': 'xxxx', 'updatedBy': 'xxxxx', 'createdAt': 1672741863059, 'updatedAt': 1672843716872, '_type': 'case_artifact', 'dataType': 'domain', 'data': '***@***', 'startDate': 1672741863059, 'tlp': 2, 'tags': ['domai'], 'ioc': True, 'sighted': False, 'message': '', 'reports': {}, 'stats': {}, 'ignoreSimilarity': False}]
>>>
Donc, on constate bien avoir avec la méthode json de Response une liste, json.dumps sur response.json retourne bien un str, et comme prévu un json.loads de response.text retourne bien un json utilisable dans un code.
Mais est-ce bien le module requests que tu utilises ?
Que ce soit get ou post le retour sera identique, tu devrais quand même regarder les types des objets que tu manipules pour comprendre ce qui fait que ça déconne, où alors tenter de donner ici un exemple reproductible du problème.
Bonne chance.
Merci pour ton aide, cependant, en remplaçant les "False" et "True" j'ai toujours la même erreur. Apparemment (d'après internet), l'erreur provient du fait que j'ai plusieurs objets dans le JSON, c'est pour cela que j'ai parlé de l'idée d'utiliser un "for" pour pouvoir séparer ces objets.
Bon, si je remplace la variable "obs" par :
observables = '[{}, {}]'Cela fonctionne, donc ce que j'ai dit plus haut ne fonctionne pas. Cela doit être autre chose qui bloc