decode_json in eine wrapper-lib

Begonnen von CoolTux, 07 Februar 2022, 13:27:59

Vorheriges Thema - Nächstes Thema

CoolTux

Hallo,

Seit Jahren kommen immer mehr und mehr Module in FHEM welche JSON Perlmodule benötigen zum en- und decoden von JSON. Je nach dem wem man Fragt ist dieses oder jenes JSON Modul zu bevorzugen. Ich selbst verwende seit einigen Jahren eine Abfrage welche JSON Module im System vorhanden sind.
Nun kam die Frage durch Beta-User auf ob es in der Tat nicht Sinnvoll wäre ein entsprechenden Wrapper Modul zu entwickeln welches nicht nur eine Abfrage nach dem Vorhanden sein eines entsprechenden Modules tätigt sondern den jeweilige decode und encode Funktionaufruf sicher verpackt.
Ich finde Beta-Users Idee gut und wäre für ein selches FHEM-JSON-Wrapper Modul.


# try to use JSON::MaybeXS wrapper
#   for chance of better performance + open code
eval {
    require JSON::MaybeXS;
    import JSON::MaybeXS qw( decode_json encode_json );
    1;
} or do {

    # try to use JSON wrapper
    #   for chance of better performance
    eval {
        # JSON preference order
        local $ENV{PERL_JSON_BACKEND} =
          'Cpanel::JSON::XS,JSON::XS,JSON::PP,JSON::backportPP'
          unless ( defined( $ENV{PERL_JSON_BACKEND} ) );

        require JSON;
        import JSON qw( decode_json encode_json );
        1;
    } or do {

        # In rare cases, Cpanel::JSON::XS may
        #   be installed but JSON|JSON::MaybeXS not ...
        eval {
            require Cpanel::JSON::XS;
            import Cpanel::JSON::XS qw(decode_json encode_json);
            1;
        } or do {

            # In rare cases, JSON::XS may
            #   be installed but JSON not ...
            eval {
                require JSON::XS;
                import JSON::XS qw(decode_json encode_json);
                1;
            } or do {

                # Fallback to built-in JSON which SHOULD
                #   be available since 5.014 ...
                eval {
                    require JSON::PP;
                    import JSON::PP qw(decode_json encode_json);
                    1;
                } or do {

                    # Fallback to JSON::backportPP in really rare cases
                    require JSON::backportPP;
                    import JSON::backportPP qw(decode_json encode_json);
                    1;
                };
            };
        };
    };
};




Grüße
Marko
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

rudolfkoenig

Dieser Code sollte sicherstellen, dass die Ergebnisse unabhaengig vom verwendeten Bibliotheken gleich sind.

Fuer bestimmte Aufgaben kann man auch die in fhem.pl enthaltene json2nameValue() und toJSON() verwenden, diese Funktionen brauchen keine weiteren Perl-Module.

Beta-User

Zitat von: rudolfkoenig am 07 Februar 2022, 13:34:18
Fuer bestimmte Aufgaben kann man auch die in fhem.pl enthaltene json2nameValue() und toJSON() verwenden, diese Funktionen brauchen keine weiteren Perl-Module.
Das ist soweit (hoffentlich) den meisten bekannt. Manchmal geht es darum, gerade die Datenstruktur in ihrem Ausgangsbestand zu erhalten und nach Perl zu überführen, da hilft j2nV nicht weiter (ich verwende das z.B. in WeekdayTimer, um weekprofile-Daten auszuwerten, in RHASSPY, an vielen Orten, um z.B. Antwortstrukturen einzulesen und ggf. neuerdings in msgDialog für Dialogstrukturen. Da hilft eine flache Struktur nicht weiter.)

toJSON hat auch ein paar Tücken, wenn die Gegenstelle auf der 100%-Einhaltung der Specs besteht (und z.B. Zahlen unbedingt ohne Quotes will, NULL haben will, ...)

In diesen Fällen muss man im Prinzip auf "irgendeine" JSON-lib ausweichen.

Zitat von: rudolfkoenig am 07 Februar 2022, 13:34:18
Dieser Code sollte sicherstellen, dass die Ergebnisse unabhaengig vom verwendeten Bibliotheken gleich sind.
Das wäre wünschenswert. ABER:
Wir haben derzeit die Situation, dass jeder Maintainer "seinen Liebling" reinvercoded (ich nehme aus Faulheit immer "use JSON;", was eigentlich einengend ist, wenn jemand "was schnelleres" oder eine PP-Variante bevorzugen würde; mir war es aber zu blöd, diesen häufiger anzutreffenden Abfrage-Code-Bandwurm von CoolTux (und anderen) einzubauen...).

Soweit ich das aus dem "typischen was ist denn da?-Massaker-Code" entnommen habe, sind die 4 Hauptfunktionen eigentlich immer da und anscheinend auch funktionsgleich.

Es ging bei dem Vorschlag gerade darum,
a) dem User die Wahl zu lassen, was er denn installiert, indem man die lib-Analyse an einer Stelle bündelt;
b) "seltsame" Ergebnisse zu vermeiden, die entstehen können, wenn im Hintergrund nicht von allen Beteiligten derselbe Mechanismus genutzt wird (da immer noch viele Module im main-Kontext werkeln, müßte das eigentlich "Spaß" bedeuten, wenn der eine decode_json aus lib A zieht und der andere aus lib B, oder?);
c) das m.E. zwingende "eval" von vornherein so einzupacken, dass FHEM nicht abschmiert, aber klar ist, wenn irgendwas schiefgegangen ist.

Darüber hinaus ist der interne Umgang mit utf8 teils "komisch". Wenn man das auf eine einheitliche Basis stellt, müßte eigentlich auch ein Plus an Konsistenz rauskommen. (Soweit mir bekannt, ist "decode_json" immer mit utf8-Ergebnis (?)).

Anders gesagt: Lieber überall dasselbe Problem als überall verschiedene Probleme wegen derselben Ursache...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

justme1968

eigentlich ist es doch so das man use JSON verwenden sollte und dieses dann intern automatisch je nach platform und perl version selber entscheiden welches backend (d.h. PP oder XS) verwendet wird. wenn man direkt XS verwendet hat man ein problem wenn es diese variante auf der platform zur laufzeit nicht gibt. wer direkt PP verwendet hat das problem das ihm optimierungen eventuell entgehen wenn es zur laufzeit XS gibt.

von daher verstehe ich gerade nicht warum wir nicht einfach überall use JSON vorschreiben und sowohl das direkte XS oder PP nicht empfehlen. ein eigener wrapper sollte auch nicht nötig sein.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

betateilchen

Zitat von: justme1968 am 07 Februar 2022, 14:07:24
verstehe ich gerade nicht warum wir nicht einfach überall use JSON vorschreiben

funktioniert vermutlich auf der Fritzkotz nicht...

*duck-und-weg*
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

justme1968

ich verwende in allen modulen use JSON und hatte noch keine klagen...
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Beta-User

Zitat von: betateilchen am 07 Februar 2022, 14:19:37
funktioniert vermutlich auf der Fritzkotz nicht...
aaaber isch 'abe garr keiner fritskoks...

Zitat von: justme1968 am 07 Februar 2022, 14:07:24
eigentlich ist es doch so das man use JSON verwenden sollte und dieses dann intern automatisch je nach platform und perl version selber entscheiden welches backend (d.h. PP oder XS) verwendet wird.
OK, Danke für den Hinweis. Das war mir bei meinem Vorschlag nicht klar, dann lasse ich es jedenfalls bei meinen Codes auch dabei (use JSON;) bewenden, Perl und mein Debian werden es schon wissen, was sie damit anfangen sollen... ;D
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

herrmannj

Hi Cooltux

das war bestimmt ne Menge Arbeit, Danke. Allerdings, wie Justme schon geschrieben hat, JSON ( Perl core since 5.14 - Mai 2011) wäre eigentlich genau dafür da...

rudolfkoenig

Ich bin auch fuer eine feste Version, sonst muss der Maintainer eines Moduls die Besonderheiten aller JSON-Bibliotheken kennen.

CoolTux

Ich gebe zu es ist schon zwei drei Jahre her, aber da habe ich in 2 Foren Einträge gefunden welche darauf hinwiesen das diese automatische Erkennung über ein einfaches use JSON; wohl nicht ganz zuverlässig funktionieren soll.
Gerade das bevorzugte schnelle MaybeXS oder auch nur das XS sollen wohl nicht erkannt werden. Ich habe dazu aber auch nie wirklich Tests durchlaufen lassen.

Hatten wir nicht den Fritzbox Support im allgemeinen abgekündigt. Habe da sowas in Erinnerung.

Wenn sich alle weitestgehend darauf einigen es so zu belassen wie es aktuell ist, ist das voll ok. Es gubt ja keine Probleme an sich bis her. Zu mindest keine die hoch gekommen sind.



Grüße
Marko
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

herrmannj

#10
für mich persönlich gesprochen: aus Unkenntnis und historisch gewachsen hab ich da auch "Kraut und Rüben". Dabei wäre das JSON (perl modul) echt umfangreich konfigurierbar. https://metacpan.org/pod/JSON Welches Backend genommen werden soll, kann der user zb per umgebungsvariable bestimmen.

Ich würde ein generelles (mandatory) "use JSON" sehr unterstützen, dann ist auch Schluss damit, dass tausend unterschiedliche JSON Bibliotheken gleichzeitig geladen sind, und sich im schlimmsten Fall gegenseitig noch stören. Für diejenigen die kein XS auf ihrem Taschenrechner installieren können wäre ja sogar json:pp als Fallback immer verfügbar.

Nachtrag: ich sehe gerade: JSON (selbst) ist nicht perl core, JSON:PP ist perl core (5.14+). Das ist imho trotzdem argumentierbar, muss dann halt per cpan installiert werden und ist zwingend.

Beta-User

Zitat von: herrmannj am 07 Februar 2022, 14:38:35
JSON ( Perl core since 5.14 - Mai 2011)
Vielleicht noch eine etwas andere Sache in diesem Zusammenhang: Es gibt ein ganzen Haufen Module, die Data::Dumper nur deswegen laden, weil "notfalls" was (= eine Datenstruktur) geloggt werden soll. Das ist aber "Speicherloch-verdächtig".
Da JSON core ist, wäre es dann nicht besser, für solche Log-Aufträge die Datenstruktur an encode_json zu übergeben? (Schon klar, dass das Schiefgehen kann, wenn gar keine gültige Datenstruktur vorliegt, und es daher nicht 1:1 vergleichbar ist, aber m.E. müsste es jedenfalls in den Fällen klappen, die mir in diese Richtung bisher über den Weg gelaufen sind).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

herrmannj

ne ich hab mich da vertan, JSON ist nicht core (nur JSON:PP). Siehe edit 2 höher. Tut dem imho keinen Abbruch