Forum: PC-Programmierung JSON Parser - JSMN, kontinuierliche Daten möglich?


von Holger K. (holgerkraehe)


Lesenswert?

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:
1
//128 bytes der Datei lesen und dann
2
result = jsmn_parse(&parser, fileBuffer, 128, tokens, 1024);
3
4
//Dann die nächsten 128Bytes und so weiter...

Leider scheint dies aber so nicht ganz zu klappen.
Der Parser parst nur die ersten 128 Zeichen und sagt dann:
1
 JSMN_ERROR_PART - JSON string is too short, expecting more JSON data

Kennt jemand diese Library?
Ist dies was ich versuche überhaupt möglich?

Danke!

: Verschoben durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wie soll ein JSON-Parser unvollständiges JSON parsen?

von Holger K. (holgerkraehe)


Lesenswert?

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.

von yesitsme (Gast)


Lesenswert?

ich glaub der fehler ist schon so gewollt da:
1
 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.

von Holger K. (holgerkraehe)


Lesenswert?

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?

von sdfgdfg (Gast)


Lesenswert?

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.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

natürlich gibt es auch für JSON stream-based Parser, die mit Callbacks 
arbeiten... google nach "json stream parser" liefert schon einige 
resultate

von ReadsNoDocos (Gast)


Lesenswert?

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...

von Dominik S. (dasd)


Lesenswert?

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).

von Dominik S. (dasd)


Angehängte Dateien:

Lesenswert?

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.

von Holger K. (holgerkraehe)


Lesenswert?

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.

von Dominik S. (dasd)


Angehängte Dateien:

Lesenswert?

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):
1
static const char *JSON_STRING =
2
  "{\"user\": \"johndoe\", \"admin\": false, \"uid\": 1000,\n  "
3
  "\"groups\": [\"users\", \"wheel\", \"audio\", \"video\"]}";

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...

von Boris O. (bohnsorg) Benutzerseite


Lesenswert?

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.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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 ;-)

von Datentechnigger (Gast)


Lesenswert?

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

von Marco H. (damarco)


Lesenswert?

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 ?

: Bearbeitet durch User
von Johnny B. (johnnyb)


Lesenswert?

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.

von Marco H. (damarco)


Lesenswert?

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.

: Bearbeitet durch User
von Bernd K. (prof7bit)


Lesenswert?

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?

von vn nn (Gast)


Lesenswert?

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...

von Marco H. (damarco)


Lesenswert?

Es scheint aber kaum welche zu geben. Warum auch immer....

Firefox wird instabil bei zu großen Json. Man kann dann keine Tabs mehr 
öffnen.

: Bearbeitet durch User
von Bernd K. (prof7bit)


Lesenswert?

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.

: Bearbeitet durch User
von Marco H. (damarco)


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.