JSON Parser - JSMN, kontinuierliche Daten möglich?

OP #5306027
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!
Gast #5306947
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.
OP #5307052
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?
Gast #5307059
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.
Gast #5307063
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...
#5307090
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).
#5307103
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.
Angehängte Dateien:
OP #5307827
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.
#5308683
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...
Angehängte Dateien:
Persönliche Seite #5308797
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.
(Firma: Brainit GmbH) #5309046
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 ;-)
Gast #5309095
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
#5478559
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 ?
#5480683
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.
#5482318
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.
Gast #5482847
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...
#5482959
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.
#5483705
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren