Hallo zusammen
Ich versuche mich gerade an JSMN, einem json parser.
https://github.com/zserge/jsmn
Es steht da, dass man die Datei auch in Stücken parsen kann.
Sozusagen aus einem stream.
Ich mache dies so:
Rufus Τ. F. schrieb:> Wie soll ein JSON-Parser unvollständiges JSON parsen?
Ich bin davon ausgegangen, dass er sich den Zustand der letzten Parsung
in &parser gemerkt hat und sobald weitere bytes hinzukommen, dort
weitermacht.
If you read json data from the stream, you can periodically call jsmn_parse and check if return value is JSMN_ERROR_PART. You will get this error until you reach the end of JSON data.
yesitsme schrieb:> ich glaub der fehler ist schon so gewollt da:> If you read json data from the stream, you can periodically call> jsmn_parse and check if return value is JSMN_ERROR_PART. You will get> this error until you reach the end of JSON data.
Misst!
Ich habe zu wenig Ram um mehrere Kilobyte an json zwischen zu speichern.
Dann muss ich wohl den parser umbauen oder mir einen anderen suchen.
Kennt jemand einen json parser für embedded, welcher streams handeln
kann?
Das JSON Format nutzt ein Objekt als root-Knoten. Solange dieser nicht
vollständig eingelesen wurde, kann dir kein Parser ein sinnvolles
Ergebnis liefern. In diesem Sinne kannst du JSON nicht im Stream
"häpchenweise" parsen.
Eine Alternative wäre mehrere vollständige kleinere JSON-Objekte zu
übertragen und zu verarbeiten.
Holger K. schrieb:> yesitsme schrieb:>> ich glaub der fehler ist schon so gewollt da:>> If you read json data from the stream, you can periodically call>> jsmn_parse and check if return value is JSMN_ERROR_PART. You will get>> this error until you reach the end of JSON data.>> Misst!
Was sollen wir messen?
>> Ich habe zu wenig Ram um mehrere Kilobyte an json zwischen zu speichern.> Dann muss ich wohl den parser umbauen oder mir einen anderen suchen.
Ich habe die JSMN Doku nun tatsächlich nicht gelesen, aber warum
schließt Du aus obigem Text wieviel RAM mindestens nötig ist? Stehen die
Mindestanforderungen tatsächlich irgendwo?
Oder hast Du dasselbe "Problem" wie JSMN: nicht genug lesen und das
Ganze nicht verstehen?
Kann es nicht sein, dass jsmn_parse wiederholt sooft aufzurufen ist
bis nicht mehr JSMN_ERROR_PART zurückgegeben wird, auch nur 128 B Pro
mal?
(f. JSON kann das durchaus bis zu 5..7 Zeilen sein - wieviele JSON Daten
hast Du denn insgesamt?)
Man kann darüber sinnieren ob die Benennung "..ERROR.." passend oder
verwirrend ist...
ReadsNoDocos schrieb:> Kann es nicht sein, dass jsmn_parse wiederholt sooft aufzurufen ist> bis nicht mehr JSMN_ERROR_PART zurückgegeben wird, auch nur 128 B Pro> mal?
Dacht ich auch erst anhand der Doku, aber es scheint nur gemeint zu
sein, dass man damit prüfen kann, ob alle Daten aus dem Stream gelesen
wurden. Die Daten müssen sich aber lokal alle in einem ausreichend
großen Buffer befinden (Stream-Daten lokal buffern, dann ganzen Buffer
an jsmn_parse füttern).
Holger K. schrieb:> Ich mache dies so:> //128 bytes der Datei lesen und dann> result = jsmn_parse(&parser, fileBuffer, 128, tokens, 1024);>> //Dann die nächsten 128Bytes und so weiter...
Ich habe eben mal was ausprobiert:
Setzte mal vor dem Aufruf von jsmn_parse jeweils "paser.pos" auf 0.
Beim letzten Aufruf (mit dem Ende des Streams) kommt dann tatsächlich
die Anzahl der Tokens zurück.
Nachteil:
Der start-index im Token-Array ("tokens") fängt dann eben für jedes
Stück vom Stream bei 0 an, siehe Anhang.
Dominik S. schrieb:> Ich habe eben mal was ausprobiert:>> Setzte mal vor dem Aufruf von jsmn_parse jeweils "paser.pos" auf 0.
Vielen Dank für deinen Input!
Ich habe mir ebenfalls den Code angeschaut und etwas ähnliches gedacht.
Hast du im JSON bei einem beliebigen Zeichen aufgehört oder bei etwas
sinnvollem wie z.B. einer Klammer?
Denn ich frage mich, wass der Parser tut, wenn er z.B. mitten in einem
String keine Daten mehr hat.
Dominik S. schrieb:> Dacht ich auch erst anhand der Doku,
Schön, dass nicht nur ich die Doku so verstanden hat.
Holger K. schrieb:> Hast du im JSON bei einem beliebigen Zeichen aufgehört oder bei etwas> sinnvollem wie z.B. einer Klammer?
Hi Holger,
ich habe beliebig aufgehört und du hast recht: das ist ein Problem...
Der JSON-String war folgender (aus dem Sample):
Bei meinem Screenshot oben sieht man auf Pos. 9 ein "Primitive", das
müsste eigentlich ein String sein.
Ich habe jetzt mal nach dem Parser-Aufruf noch einen Check hinzugefügt,
ob alle Bytes im Parser verarbeitet wurden. Hierzu schaue ich, ob ob
"parser.pos" der Länge meines Bufferinhalts entspricht.
Wenn nicht gebe ich die Zeichen nochmal mit rein beim nächsten mal.
Wenn die Daten aus einem echten Stream kommen (und nicht wie bei mir aus
einem "gefake'ten") ist das aber natürlich etwas blöd. Dann müsste man
den Parser vllt aus einem Ringbuffer füttern.
Ich hab meinen Code mal in den Anhang gepackt...
Bei stark begrenztem Arbeitsspeicher auf JSON setzen, wirklich? Ein
Baummodell mit einem Streaming-Ansatz interpretieren, etwas mutig? Viele
Steuerzeichen im Verhältnis zur Nutzlast, aus Ineffizienzgründen? Ich
schlage vor, du schreibst etwas Mikrocontroller-Code, einen passenden
Interpreter zum JSON in ein FPGA zu brennen UND ich schenke dir dazu
eine schönere Kneifzange, in Zukunft deine Hose anzuziehen.
Boris O. schrieb:> Bei stark begrenztem Arbeitsspeicher auf JSON setzen, wirklich?
Wie ich oben schon mal geschrieben hatte: Das ist überhaupt kein
problem, solange man den richtigen Parser einsetzt. stream-based, in
diesem Fall.
Einen tree-based (DOM) Parser zu verwenden ist zum Scheitern verurteilt.
Trotz aller Klimmzüge.
Man könnte sich allerdings noch tiefer in den Morast begeben, und auf
XML wechseln ;-)
Michael R. schrieb:> Boris O. schrieb:>> Bei stark begrenztem Arbeitsspeicher auf JSON setzen, wirklich?>> Wie ich oben schon mal geschrieben hatte: Das ist überhaupt kein> problem, solange man den richtigen Parser einsetzt. stream-based, in> diesem Fall.>> Einen tree-based (DOM) Parser zu verwenden ist zum Scheitern verurteilt.> Trotz aller Klimmzüge.>> Man könnte sich allerdings noch tiefer in den Morast begeben, und auf> XML wechseln ;-)
Die nochmalige Steigerung: Forumsposts.
SCNR
Ich muss das noch mal hoch holen da ich ein ähnliches Problem habe.
Auf der Client Seite (Browser) ist Speicher nicht unbedingt das Problem.
Das wirkliche Problem ist das dass parsen zu lange dauert.
Hier mal schön gezeigt
https://joshzeigler.com/technology/web-development/how-big-is-too-big-for-json
Man beachte den Speicherverbrauch von Firefox !
Nebenbei auch eine Menge Speicher belegt. Da einzige weg bleibt wohl das
Streaming. Wenn die Struktur bekannt ist und man weiß was man heraus
fischen will ist das eine gute Lösung.
Für mein Projekt habe ich das hier entdeckt http://oboejs.com/
Es erlaubt sogar offene Streams! Also ein Json was nie geschlossen wird
und immer wieder beschrieben wird.
Hat das mal jemand benutzt ?
Ich weiss ja nicht auf welcher Plattform das laufen soll, aber es macht
wirklich keinen Sinn, JSON z.B. auf einem ATTINY parsen zu wollen.
Entweder man nimmt ein effizienteres Übertragungsprotokoll (mit
Binärdaten) oder man nimmt eine Plattform mit genügend Resourcen um ein
komplettes JSON Objekt in Textform buffern und verarbeiten zu können.
Alles andere wird wohl nicht zu einem befriedigenden Ergebnis führen.
Nunja das Problem ist eben das man mit dem meisten IOT Diensten dann ein
Problem bekommt. AWS, Google geben als Response Json zurück.
An sich ist das auch kein Problem, Geschwindigkeit spielt bei einen
Sensor bzw. Aktor weniger eine Rolle. Ob 300ms später das Relais
schaltet ist eigentlich Wurst. Hintereinander folgende Pakete fängt das
AWS damit ab das dass Gerät seinen Status zurückmeldet. Drückst du 100
mal auf den Knopf wird das Gerät irgend wann den letzten Status
annehmen. Ohne das 99 Pakete versendet wurden.
Nur ein Problem hat man mit einen AVR, ARM etc. auf jeden Fall. Der
Speicher ist nicht sehr groß, zumindest über das Maß eines TCP/IP Stacks
hinaus.
Wenn man die Daten nun Seriell einliest kann man auch 100MB abarbeiten
;).
In der Regel schaut man aber zu das dass Json in einen TCP/IP Frame
passt um genau solche Probleme zu vermeiden.
Denn wenn du es in mehreren Frames teilst sind wir genau an dem Problem
was hier besprochen wird. Entweder du schiebst das in einen so großen
Buffer oder die liest die Daten Seriell ein.
Holger K. schrieb:> Ich habe zu wenig Ram um mehrere Kilobyte an json zwischen zu speichern.
Mich würde mal interessieren was das für ein Thing werden soll wenns mal
fertig ist. Ich nehme an Du peilst sehr hohe Stückzahlen an wenn Du
wegen ein paar wenigen Kilobyte RAM schon so geizen musst?
Johnny B. schrieb:> Ich weiss ja nicht auf welcher Plattform das laufen soll, aber es macht> wirklich keinen Sinn, JSON z.B. auf einem ATTINY parsen zu wollen.> Entweder man nimmt ein effizienteres Übertragungsprotokoll (mit> Binärdaten) oder man nimmt eine Plattform mit genügend Resourcen um ein> komplettes JSON Objekt in Textform buffern und verarbeiten zu können.> Alles andere wird wohl nicht zu einem befriedigenden Ergebnis führen.
Was waren das noch für Zeiten, als man effizienten Code schrieb...
serielle Parser sind nun wirklich kein Hexenwerk...
vn nn schrieb:> Was waren das noch für Zeiten, als man effizienten Code schrieb...
Da hat man auch noch kein JSON verwendet sondern die Datenformate und
Protokolle so ausgewählt daß sie zu den übertragenen Daten passen.
Und effizienten Code schreibt man auch heute noch, nur die
Rahmenbedingungen und die Zielsetzungen haben sich geändert. In einer
Umgebung in der man JSON für diese Aufgabe auswählt wird der Speicher
nicht mehr in Kilobyte sondern in Megabyte gemessen, der Parser kann
trotzdem effizient sein.
Die Idee von Json ist eine andere ;), die wäre das Daten von Mensch und
Maschine gelesen werden können. Das macht es einfacher die Daten am Ende
auszuwerten. Da sie ohne Hintergrund wissen gelesen werden können.
Genau deswegen verwende ich Json für mein Projekt. Ohne Kenntnis vom
Standard sind die Daten Nutzbar.