Comment lire JSON de prise en python? (Incremental parser JSON)
J'ai un socket ouvert et j'aimerais lire quelques données json. Le problème est que le json
module de la bibliothèque standard ne peut analyser à partir des chaînes de caractères (load
ne lit que l'ensemble du dossier et des appels loads
à l'intérieur) Il vérifie que tout le chemin à l'intérieur du module tout dépend du paramètre de chaîne.
C'est un réel problème avec les sockets puisque vous ne pourrez jamais lire tout cela à la chaîne et vous ne savez pas comment le nombre d'octets à lire avant de l'analyser.
Donc mes questions sont: Est-il un (simple et élégant) solution de contournement? Est-il une autre librairie json qui peut analyser les données de manière incrémentielle? Est-ce la peine de l'écrire moi-même?
Edit: C'est XBMC jsonrpc api. Il n'y a aucun message d'enveloppes, et je n'ai aucun contrôle sur le format. Chaque message peut être sur une seule ligne ou sur plusieurs lignes.
Je pourrais écrire un simple analyseur qui a besoin seulement getc fonction d'une certaine forme, et de le nourrir à l'aide de s.recv(1)
, mais ce n'est pas un très pythonic solution et je suis un peu paresseux pour le faire 🙂
OriginalL'auteur cube | 2011-09-07
Vous devez vous connecter pour publier un commentaire.
Ce que vous voulez(ed) est ijson, un incremental parser json.
Il est disponible ici: https://pypi.python.org/pypi/ijson/ . L'usage doit être simple (copie de la page):
(pour ceux qui préfèrent quelque chose d'auto-contenue - dans le sens où elle se fonde uniquement sur la bibliothèque standard: j'ai écrit hier un petit wrapper autour de json, mais juste parce que je ne savais pas à propos ijson. Il est probablement beaucoup moins efficace.)
MODIFIER: depuis que j'ai découvert qu'en fait (un cythonized version) mon approche a été beaucoup plus efficace que ijson, j'ai emballé comme une bibliothèque indépendante - voir ici aussi pour des bruts de référence: http://pietrobattiston.it/jsaone
OriginalL'auteur Pietro Battiston
Edit: étant donné que vous n'êtes pas à la définition du protocole, ce n'est pas utile, mais il pourrait être utile dans d'autres contextes.
En supposant que c'est un flux (TCP) socket, vous devez mettre en place votre propre message cadrage mécanisme (ou utiliser un protocole de niveau supérieur qui le fait). Un moyen simple est de définir chaque message comme un entier de 32 bits longueur de champ, suivi par le nombre d'octets de données.
Expéditeur: prenez la longueur du JSON paquet, pack de 4 octets avec la
struct
module, l'envoyer sur le socket, puis envoyer le JSON paquet.Récepteur: répète la lecture de la douille jusqu'à ce que vous avez au moins 4 octets de données, d'utilisation
struct.unpack
déballage de la longueur. Lire dans le socket jusqu'à ce que vous avez au moins que beaucoup de données, et c'est votre JSON paquet; tout ce qui reste est la longueur du message suivant.Si à un certain moment, vous allez avoir à envoyer des messages qui consiste en quelque chose d'autre que JSON sur le même socket, vous pouvez envoyer un message de type de code entre la longueur de la charge utile de données; félicitations, vous avez encore inventé un autre protocole.
Une autre, un peu plus standard, la méthode est DJB de Netstrings protocole; il est très similaire au système proposé ci-dessus, mais avec le texte codé longueurs au lieu de binaire; il est directement pris en charge par des cadres comme Twisted.
OriginalL'auteur Russell Borogove
Si vous obtenez le JSON à partir d'un flux HTTP, utilisez le
Content-Length
- tête pour obtenir la longueur de données JSON. Par exemple:OriginalL'auteur Adam Rosenfield
Vous avez le contrôle sur le json? Essayez d'écrire chaque objet que d'une seule ligne. Puis faire un readline appel sur le socket comme décrit ici.
OriginalL'auteur Gringo Suave
L'écrémage de la XBMC JSON-RPC docs, je pense que vous voulez existant JSON-RPC bibliothèque, vous pouvez prendre un coup d'oeil à:
http://www.freenet.org.nz/dojo/pyjson/
Si ce n'est pas adapté pour quelque raison que ce soit, il me semble que chaque demande et la réponse est contenue dans un objet JSON (plutôt qu'un lâche JSON primitif qui peut être une chaîne de caractères, tableau, ou le nombre), de sorte que l'enveloppe que vous cherchez est "{ ... } " qui définit un objet JSON.
Donc, je veux essayer quelque chose comme (pseudo-code):
"\"{"
.Avez-vous essayé d'utiliser une bibliothèque existante?
J'ai essayé quelques JSONRPC bibliothèques. La plupart d'entre eux sont trop compliquées, ne peut pas s'exécuter sur un raw TCP connexion, ou ne peut fonctionner en tant que serveur. La seule parser JSON que j'ai essayé était celui de la bibliothèque standard.
Je suppose que je ne suis pas encore au clair sur les paramètres de votre problème. Votre application est dans le client ou le rôle de serveur? Attendez-vous à utiliser le raw TCP connexion pour plus que juste JSON-RPC?
Mon application est un client. Serveur répond, soit répond à mes appels de méthode ou envoie des notifications qui vont sans réponse. Tous les messages envoyés sur les sockets sont des objets JSON ou de tableaux.
OriginalL'auteur Russell Borogove
Vous pouvez trouver JSON-RPC utile pour cette situation. C'est un appel de procédure à distance protocole qui devrait vous permettre d'appeler les méthodes exposées par le XBMC JSON-RPC. Vous pouvez trouver les spécifications sur Trac.
OriginalL'auteur dman