String nach WinHttpRequest-Abfrage konvertieren Topic is solved

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

User avatar
LuckyJoe
Posts: 341
Joined: 02 Oct 2013, 09:52

String nach WinHttpRequest-Abfrage konvertieren

Post by LuckyJoe » 12 Apr 2024, 11:54

Hallo zusammen,

ich bekomme nach einer WinHttpRequest-Abfrage folgendes Ergebnis in einer MsgBox:
{"name":"j\u00fcrgen","name_sanitized":"J\u00fcrgen","country":"","gender":"male","samples":9431,"accuracy":99,"duration":"12ms","credits_used":1}

Wie bekomme ich den String so konvertiert, dass die Umlaute korrekt dargestellt werden? Ich habe hier einen Tipp von just me gefunden:

Code: Select all

FixUTF8(ByRef input) {
	VarSetCapacity(tempVar, StrPut(input, "CP0")) ; <<<< nach ANSI konvertieren
	StrPut(input, &tempVar, "CP0") ; <<<< nach ANSI konvertieren
	Return StrGet(&tempVar, "UTF-8")
}
der aber nicht klappt.

Wie bekomme ich die MsgBox noch etwas simpler und "schöner" hin, z.B. nur bestimmte Daten und diese mit deutschen Begriffen, z.B.:
Jürgen: männlich (Genauigkeit: 99 / Proben: 9431)

Danke für's Lesen.
Herzliche Grüße aus dem Rheinland
Lucky Joe

garry
Posts: 3771
Joined: 22 Dec 2013, 12:50

Re: String nach WinHttpRequest-Abfrage konvertieren

Post by garry » 12 Apr 2024, 13:30

kannst Du versuchen ob in diesem Beispiel die Zeichen korrekt sind ? ( Variable 'H' , mit Deinem URL )

Code: Select all

F1:=a_desktop . "\test.hta"
url:="https://blog.fefe.de/?css="
whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   Whr.Open("GET", url, true)
   Whr.Send()
   Whr.WaitForResponse()
   Arr := Whr.responseBody
   pData := NumGet(ComObjValue(arr) + 8 + A_PtrSize)
   length := arr.MaxIndex() + 1
   H := StrGet(pData, length, "UTF-8")
fileappend,%h%,%F1%,utf-8
try,run,%f1%
exitapp
esc::exitapp

User avatar
LuckyJoe
Posts: 341
Joined: 02 Oct 2013, 09:52

Re: String nach WinHttpRequest-Abfrage konvertieren

Post by LuckyJoe » 13 Apr 2024, 01:48

Hallo garry,

vielen Dank für deinen Ansatz, aber die Darstellung ist unverändert ("J\u00fcrgen").
Herzliche Grüße aus dem Rheinland
Lucky Joe

User avatar
LuckyJoe
Posts: 341
Joined: 02 Oct 2013, 09:52

Re: String nach WinHttpRequest-Abfrage konvertieren

Post by LuckyJoe » 13 Apr 2024, 03:34

Hallo noch einmal,

bei dem Json-String werden die Umlaute (und ggf. andere "Sonderzeichen") offensichtlich in einem Unicode-Format angegeben, das mit "\u" beginnt, gefolgt von 4 Hexadezimalzeichen. In einem AHK-Forum habe ich eine Funktion von jNizM gefunden, die Hex in Dec umwandelt:

Code: Select all

HexToDec(hex)
{
    VarSetCapacity(dec, 66, 0)
    , val := DllCall("msvcrt.dll\_wcstoui64", "Str", hex, "UInt", 0, "UInt", 16, "CDECL Int64")
    , DllCall("msvcrt.dll\_i64tow", "Int64", val, "Str", dec, "UInt", 10, "CDECL")
    return dec
}
Also z.B.:

Code: Select all

MsgBox % Chr(HexToDec("00fc"))		; -> ü
Damit könnte ich die 4 Hex-Zeichen konvertieren.

Wie kann ich den String aber insgesamt hinsichtlich der Zeichen "\u" und den folgenden 4 Hex-Zeichen untersuchen? Gibt es da eine Möglichkeit mit RegEx?
Herzliche Grüße aus dem Rheinland
Lucky Joe

garry
Posts: 3771
Joined: 22 Dec 2013, 12:50

Re: String nach WinHttpRequest-Abfrage konvertieren  Topic is solved

Post by garry » 13 Apr 2024, 10:26

von @Rohwedder

Code: Select all

;- Format multiple characters by char code?    / Rohwedder
;- https://www.autohotkey.com/boards/viewtopic.php?f=76&t=109066
;-
aa={"name":"j\u00fcrgen","name_sanitized":"J\u00fcrgen","country":"","gender":"male","samples":9431,"accuracy":99,"duration":"12ms","credits_used":1}
ab:=decode_utf8(aa)
msgbox,%ab%
return
;_
decode_utf8(charcode_string) {
    spo := 1
    out := ""
    while (fpo:=RegexMatch(charcode_string, "i)\\u([0-9A-F]{1,6})", m, spo))
    {
        out .= SubStr(charcode_string, spo, fpo-spo)
        spo := fpo + StrLen(m)
        if (m1)
            out .= Chr("0x" m1)
    }
    return out SubStr(charcode_string, spo)
}
;=====================================================================
Beispiel in einem loop ... ( muss vorerst diese richtigen Linien finden)

Code: Select all

#Warn
e:=""
e4=
(
{"name":"j\u00fcrgen","name_sanitized":"J\u00fcrgen","country":"","gender":"male","samples":9431,"accuracy":99,"duration":"12ms","credits_used":1}
{"name":"j\u00fcrgen","name_sanitized":"\u4f60\u597d","country":"","gender":"female","samples":9430,"accuracy":98,"duration":"12ms","credits_used":1}
{"name":"j\u00fcrgen","name_sanitized":"星期日 十一月","country":"","gender":"male","samples":9429,"accuracy":97,"duration":"12ms","credits_used":1}
)
loop,parse,e4,`n,`r
 {
 aa:=a_loopfield
 ab:=decode_utf8(aa)
 stringreplace,ab,ab,`",,all
 StringSplit,a,ab,`,
 StringSplit,b,a2,`: 
 StringSplit,c,a4,`:
 if (c2="male")
   c2:="männlich"
 if (c2="female")
   c2:="weiblich"
 StringSplit,d,a6,`:
 StringSplit,e,a5,`:
 e .= b2 . ": " . c2 . " (Genauigkeit: " . d2 . " / Proben: " . e2 . ")`r`n"
 }
msgbox,%e%
return
;------------------
;- Format multiple characters by char code?    / Rohwedder
;- https://www.autohotkey.com/boards/viewtopic.php?f=76&t=109066
;-
decode_utf8(charcode_string) {
    spo := 1
    out := ""
    while (fpo:=RegexMatch(charcode_string, "i)\\u([0-9A-F]{1,6})", m, spo))
    {
        out .= SubStr(charcode_string, spo, fpo-spo)
        spo := fpo + StrLen(m)
        if (m1)
            out .= Chr("0x" m1)
    }
    return out SubStr(charcode_string, spo)
}
;=====================================================================
RESULT :

Code: Select all

Jürgen: männlich (Genauigkeit: 99 / Proben: 9431)
你好: weiblich (Genauigkeit: 98 / Proben: 9430)
星期日 十一月: männlich (Genauigkeit: 97 / Proben: 9429)

User avatar
LuckyJoe
Posts: 341
Joined: 02 Oct 2013, 09:52

Re: String nach WinHttpRequest-Abfrage konvertieren

Post by LuckyJoe » 13 Apr 2024, 13:36

Hallo garry,

toll! Danke! :clap:

Den "Decoder" hatte ich als ähnliches Beispiel bei der AHK-Hilfe auch gefunden, habe mich aber nicht darangetraut, weil mir das zu kompliziert erschien. Einen ähnlichen RegEx-Ausdruck hatte ich aber auch schon gefunden:

Code: Select all

[{\\\\}][u][\dA-Fa-f]{4}

Auch bei der Schleife bin ich zu einem Ergebnis gekommen, wenngleich auch etwas länger:

Code: Select all

json = {"name":"\u00fcrg\u00fcn\u00e9","name_sanitized":"\u00dcrg\u00fcn\u00e9","country":"","gender":"female","samples":9431,"accuracy":99,"duration":"12ms","credits_used":1}
jsonF := DecodeUTF8(json)
jsonF := StrReplace(jsonF, """", "")

For Index, jsonTeil in StrSplit(jsonF, ",", "{" "}")
{
    Element := StrSplit(jsonTeil, ":")
    If Element[1] = "name"
        Antwort .= "Eingabe: " . chr(9) . Element[2] . "`n"
    If Element[1] = "name_sanitized"
        Antwort .= "Korrektur: " . chr(9) . Element[2] . "`n"
    If Element[1] = "gender"
    {
        Antwort .= "Geschlecht: "
        Switch Element[2]
        {
            Case "male":    Antwort .= chr(9) . "männlich`n"
            Case "female":  Antwort .= chr(9) . "weiblich`n"
            Case "unknown": Antwort .= chr(9) . "unbekannt`n"
        }
    }
    If Element[1] = "samples"
        Antwort .= "Einträge: " . chr(9) . Element[2] . "`n"
    If Element[1] = "accuracy"
        Antwort .= "Genauigkeit: " . chr(9) . Element[2]
}

MsgBox, % Antwort
Return

; _________________________
DecodeUTF8(ThisString) {
    Pos := 1
    out := ""
    While (FirstPos := RegexMatch(ThisString, "\\u([\dA-Fa-f]{4})", Match, Pos))
    {
        out .= SubStr(ThisString, Pos, FirstPos - Pos)
        Pos := FirstPos + StrLen(Match)
        If (Match1)
            out .= Chr("0x" Match1)
    }
    Return out SubStr(ThisString, Pos)
}

Danke dir nochmals für deine Mühen!
Herzliche Grüße aus dem Rheinland
Lucky Joe

just me
Posts: 9467
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: String nach WinHttpRequest-Abfrage konvertieren

Post by just me » 17 Apr 2024, 04:22

Moin,

es gibt hier ein Tool von @teadrinker, das JSON-Strings in AHK-Objekte transformiert. Dabei werden die 'kodierten' Umlaute automatisch 'enkodiert' und wahrscheinlich auch etwaige weitere notwendige Usetzungen erledigt. Für Deine JSON-Antwort sollte es sich deshalb gut eignen.

Auf die Daten im AHK-Objekt kannst Du über die Keynamen (name, name_sanitized, etc.) direkt zugreifen. Das sollte auch die Formatierung der Ausgabe erleichtern:

Code: Select all

#Requires AutoHotkey v1.1.33
#NoEnv
SetWorkingDir, %A_ScriptDir%

JSON = {"name":"j\u00fcrgen","name_sanitized":"J\u00fcrgen","country":"","gender":"male","samples":9431,"accuracy":99,"duration":"12ms","credits_used":1}
AHKO := JSON2AHK(JSON) ; AHK-Objekt

KeysJSON := ["name", "name_sanitized", "gender", "samples", "accuracy"]
KeysLoc  := ["Eingabe", "Korrektur", "Geschlecht", "Einträge", "Genauigkeit"]

Antwort := ""
For Index, Key In KeysJSON
{
   Wert := AHKO[Key]
   If (Key = "gender")
   {
      Switch Wert
      {
         Case "male":    Wert := "männlich"
         Case "female":  Wert := "weiblich"
         Case "unknown": Wert := "unbekannt"
      }
   }
   Antwort .= KeysLoc[Index] . ": " . Chr(9) . Wert . "`n"
}

MsgBox, % Antwort
ExitApp

; ======================================================================================================================
; Originally released by teadrinker -> https://www.autohotkey.com/boards/viewtopic.php?p=333543#p333543
; ======================================================================================================================
JSON2AHK(JSON, Recursive := False) {
   Local
   Static Doc := ComObjCreate("htmlfile")
        , __  := Doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
        , JS  := Doc.parentWindow
   If (!Recursive)
      Obj := JSON2AHK(JS.eval("(" . JSON . ")"), True)
   Else If !IsObject(JSON)
      Obj := JSON
   Else If (JSON.toString() != "[object Object]") {
      Obj := []
      Loop % JSON.length
         Obj.Push(JSON2AHK(JSON[A_Index - 1], True) )
   }
   Else {
      Obj := {}
      Keys := JS.Object.keys(JSON)
      Loop % Keys.length {
         K := Keys[A_Index - 1]
         Obj[K] := JSON2AHK(JSON[K], True)
      }
   }
   Return Obj
}

User avatar
LuckyJoe
Posts: 341
Joined: 02 Oct 2013, 09:52

Re: String nach WinHttpRequest-Abfrage konvertieren

Post by LuckyJoe » 17 Apr 2024, 09:06

Hallo just me,

wow, Danke! ... so schön schlank - auch wenn ich durch die Funktion nicht durchblicke ... aber ich fahre auch Auto und blicke durch den Motor nicht durch :-)
Herzliche Grüße aus dem Rheinland
Lucky Joe

garry
Posts: 3771
Joined: 22 Dec 2013, 12:50

Re: String nach WinHttpRequest-Abfrage konvertieren

Post by garry » 17 Apr 2024, 11:59

@just me vielen Dank . Habe nochmals mit Loop versucht, scheint OK ...

Code: Select all

;- String nach WinHttpRequest-Abfrage konvertieren 
;- https://www.autohotkey.com/boards/viewtopic.php?p=568355#p568355

#Requires AutoHotkey v1.1.33
#Warn
#NoEnv
SetWorkingDir, %A_ScriptDir%
e4=
(
{"name":"j\u00fcrgen1","name_sanitized":"J\u00fcrgen1","country":"","gender":"male","samples":9431,"accuracy":99,"duration":"12ms","credits_used":1}
{"name":"j\u00fcrgen2","name_sanitized":"\u4f60\u597d","country":"","gender":"female","samples":9430,"accuracy":98,"duration":"12ms","credits_used":1}
{"name":"j\u00fcrgen3","name_sanitized":"星期日 十一月","country":"","gender":"male","samples":9429,"accuracy":97,"duration":"12ms","credits_used":1}
)
Antwort  := ""
loop,parse,e4,`n,`r
 {
 JSON:=a_loopfield
 AHKO     := JSON2AHK(JSON)                                                         ;- AHK-Objekt
 KeysJSON := ["name", "name_sanitized", "gender", "samples", "accuracy"]
 KeysLoc  := ["Eingabe  ", "Korrektur", "Geschlecht", "Einträge  ", "Genauigkeit"]
 For Index, Key In KeysJSON
  {
   Wert := AHKO[Key]
   If (Key = "gender")
   {
      Switch Wert
      {
      Case "male":    Wert := "männlich"
      Case "female":  Wert := "weiblich"
      Case "unknown": Wert := "unbekannt"
      }
   }
   Antwort .= KeysLoc[Index] . ": " . Chr(9) . Wert . "`r`n"
  }
 Antwort .= "-----------------------------------`r`n"  
 }
MsgBox, % Antwort
ExitApp
; ======================================================================================================================
; Originally released by teadrinker -> https://www.autohotkey.com/boards/viewtopic.php?p=333543#p333543
; ======================================================================================================================
JSON2AHK(JSON, Recursive := False) {
   Local
   Static Doc := ComObjCreate("htmlfile")
        , __  := Doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
        , JS  := Doc.parentWindow
   If (!Recursive)
      Obj := JSON2AHK(JS.eval("(" . JSON . ")"), True)
   Else If !IsObject(JSON)
      Obj := JSON
   Else If (JSON.toString() != "[object Object]") {
      Obj := []
      Loop % JSON.length
         Obj.Push(JSON2AHK(JSON[A_Index - 1], True) )
   }
   Else {
      Obj := {}
      Keys := JS.Object.keys(JSON)
      Loop % Keys.length {
         K := Keys[A_Index - 1]
         Obj[K] := JSON2AHK(JSON[K], True)
      }
   }
   Return Obj
}
;=========================================================================================

just me
Posts: 9467
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: String nach WinHttpRequest-Abfrage konvertieren

Post by just me » 17 Apr 2024, 13:07

LuckyJoe wrote:... so schön schlank - auch wenn ich durch die Funktion nicht durchblicke ...
Wenn Du damit teadrinkers Funktion meinst, ich verstehe auch nicht wirklich, wie das funktioniert. Ich verstehe aber immerhin, dass die in dem erzeugten IE-Objekt eingebettete JavaScript-Engine irgendwie dafür genutzt wird. Ansonsten denke ich auch: Schön wenn's funktioniert, warum sollte man das unbedingt verstehen müssen.

Ich schlage mich z.B. seit der Grundschule mit folgendem Problem herum: Wie genau soll ich mir -3 Äpfel vorstellen? Die Rechnerei scheint aber im Allgemeinen gut zu funktionieren. Deshalb habe ich meinen Widerstand aufgegeben. Meine Schwester hatte ein ähnliches Problem mit Bananen!

Doch es bleibt ein quälender kleiner Zweifel. Vielleicht ist das mit den negativen Zahlen doch der falsche Ansatz und der Grund für unsere Probleme mit der Unendlichkeit.

garry
Posts: 3771
Joined: 22 Dec 2013, 12:50

Re: String nach WinHttpRequest-Abfrage konvertieren

Post by garry » 17 Apr 2024, 13:36

@just me , ich konnte Deinen Skript nachvollziehen aber ich hätte es nicht hingekriegt . Gutes JSON Beispiel für's nächstemal .
Funktion verstehe ich auch nicht , ist ein guter bestehender Baustein zum weiterverwenden ( dank an @teadrinker )
Mit -3 Aprikosen geht es : wenn ich 4 Aprikosen dazulege , habe ich 1 Aprikose ... :)
-oder
.. es sind -3 Leute im Raum . Wieviel Leute müssen reinkommen damit der Raum leer ist ?
Image

Post Reply

Return to “Ich brauche Hilfe”