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
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 (https://metacpan.org/pod/Data::Dumper) selbst rausfinden.
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
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.
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.