Hauptmenü

[gelöst:] String zu Hash

Begonnen von JensS, 11 Februar 2021, 19:58:42

Vorheriges Thema - Nächstes Thema

JensS

Hallo, kann mir bitte jemand helfen, einen String in ein Hash zu schreiben. Ich dachte alles richtig gemacht zu haben aber ...
In einem Reading steckt ein JSON-String. Diesen habe ich ausgelesen und diverse Zeichen ersetzt, dass ein String rauskommt, den man in ein Hash schreiben kann.
Reading lastIntentPayload:{"Device":"Taimer","Name":"Kartoffel","input":"setze den Kartoffel Taimer auf 20 minuten","intent":"RhasspySetTimer","min":20,"probability":1,"rawInput":"setze den kartoffel taimer auf zwanzig minuten","requestType":"voice","sessionId":"Wohnzimmer-alexa-324dd3c5-7f7b-4ee5-a514-fc4632ef4c8a","siteId":"Wohnzimmer"}
Code:sub Namen(){
my ($inhalt) = $defs{Rhasspy}->{READINGS}{lastIntentPayload}{VAL};
$inhalt =~ s/:/=>/g;
$inhalt =~ s/{/(/g;
$inhalt =~ s/}/)/g;
my %ausgabe = $inhalt;
return "String: $inhalt\nHashelement: $ausgabe{'Device'}\n";
};

Ausgabe:String: ("Device"=>"Taimer","Name"=>"Kartoffel","input"=>"setze den Kartoffel Taimer auf 20 minuten","intent"=>"RhasspySetTimer","min"=>20,"probability"=>1,"rawInput"=>"setze den kartoffel taimer auf zwanzig minuten","requestType"=>"voice","sessionId"=>"Wohnzimmer-alexa-324dd3c5-7f7b-4ee5-a514-fc4632ef4c8a","siteId"=>"Wohnzimmer")
Hashelement:

Der String sieht doch gut aus. Was fehlt oder ist falsch?
Gruß Jens
Debian auf APU2C4, HM-CFG-USB2, SIGNALduino, HM-ES-PMSw1-Pl, TFA 30.3121, TFA 30.3125, ITS-150, PIR-5000, configurable Firmata USB & LAN, 1-wire: DS-18B20, DS-18S20, DS-2408, DS-2413, diverse I2C-Komponenten, zigbee2mqtt, ESPEasy etc.

Christoph Morrison

lastIntentPayload ist doch ein JSON-String, warum dekodierst du den nicht einfach richtig mit einem JSON-Modul in einen Hash?

Zitat$defs{Rhasspy}->{READINGS}{lastIntentPayload}{VAL}

Dafür gibt es ReadingsVal().

Zitatmy %ausgabe = $inhalt;

Damit machst du aus %ausgabe einen Skalar, mehr nicht. Dein Format für deine Skalar-Datenstruktur ist schon falsch formatiert und du müsstest so eine Datenstruktur schon mit eval o.ä. zurück in eine andere wandeln. Nimm einfach JSON und decode_json.

Sowas kannst du übrigens gut mit Data::Dumper selbst rausfinden.

JensS

Vielen Dank Christoph,

tatsächlich nutze ich momentan JSON. Da in FHEM mit Hashes gearbeitet wird, dachte ich es mal zu probieren.
Dein Tipp hat geholfen. Mit my %ausgabe = eval($inhalt);erhalte ich den sehnsüchtig erwarteten Wert des Key Device.

Gruß Jens
Debian auf APU2C4, HM-CFG-USB2, SIGNALduino, HM-ES-PMSw1-Pl, TFA 30.3121, TFA 30.3125, ITS-150, PIR-5000, configurable Firmata USB & LAN, 1-wire: DS-18B20, DS-18S20, DS-2408, DS-2413, diverse I2C-Komponenten, zigbee2mqtt, ESPEasy etc.

Christoph Morrison

Zitat von: JensS am 11 Februar 2021, 20:39:36
Vielen Dank Christoph,

tatsächlich nutze ich momentan JSON. Da in FHEM mit Hashes gearbeitet wird, dachte ich es mal zu probieren.
Dein Tipp hat geholfen. Mit my %ausgabe = eval($inhalt);erhalte ich den sehnsüchtig erwarteten Wert des Key Device.

Das freut mich, aber warum nutzt du nicht nur json_decode und bekommst so ohne eval und eigene Transformierung einen Hash?


use Data::Dumper;
use feature 'say';
use JSON;

my $lastIntentPayload = q(
    {
        "Device": "Taimer",
        "Name": "Kartoffel",
        "input": "setze den Kartoffel Taimer auf 20 minuten",
        "intent": "RhasspySetTimer",
        "min": 20,
        "probability": 1,
        "rawInput": "setze den kartoffel taimer auf zwanzig minuten",
        "requestType": "voice",
        "sessionId": "Wohnzimmer-alexa-324dd3c5-7f7b-4ee5-a514-fc4632ef4c8a",
        "siteId": "Wohnzimmer"
    }
);

my $json = decode_json($lastIntentPayload);
say Data::Dumper->Dump( [ $json, $json->{Device} ], [qw( lastIntentPayload Device )] );


ergibt:


$lastIntentPayload = {
                       'input' => 'setze den Kartoffel Taimer auf 20 minuten',
                       'Device' => 'Taimer',
                       'siteId' => 'Wohnzimmer',
                       'intent' => 'RhasspySetTimer',
                       'sessionId' => 'Wohnzimmer-alexa-324dd3c5-7f7b-4ee5-a514-fc4632ef4c8a',
                       'rawInput' => 'setze den kartoffel taimer auf zwanzig minuten',
                       'requestType' => 'voice',
                       'min' => 20,
                       'Name' => 'Kartoffel',
                       'probability' => 1
                     };
$Device = 'Taimer';


Das ist doch deutlich robuster als deine Herangehensweise.

JensS

#4
Das Rhasspy-Modul gibt kein JSON aus, daher habe ich lediglich das Reading. Aktuell nutze ich: my ($lastIntentPayload) = $defs{Rhasspy}->{READINGS}{lastIntentPayload}{VAL};
my $ref = JSON->new->decode($lastIntentPayload);
my $Name = encode('cp-1252',$ref->{'Device'});
, was auch funktioniert. Möchte aber dazulernen, wie man das verbessern kann. Da gibt es so viel, wovon ich noch nicht weiß, das es das gibt. Z.B., wie finde ich den Namen des Devices heraus, welches meine sub aufruft? In meinem Fall heißt es Rhasspy. Bei anderen Usern wird das nicht mehr passen.
Debian auf APU2C4, HM-CFG-USB2, SIGNALduino, HM-ES-PMSw1-Pl, TFA 30.3121, TFA 30.3125, ITS-150, PIR-5000, configurable Firmata USB & LAN, 1-wire: DS-18B20, DS-18S20, DS-2408, DS-2413, diverse I2C-Komponenten, zigbee2mqtt, ESPEasy etc.