Wie bekomme ich die doppelten Anführungszeichen im JSON-String weg

  • VB.NET

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von Yanbel.

    Wie bekomme ich die doppelten Anführungszeichen im JSON-String weg

    Ich muss/möchte per POST einen JSON-String an einen Webserver senden. Soweit hab ich das auch alles gebaut, aber wie bekomme ich es hin dass ich da jetzt anstelle der doppelten Anführungszeichen nur ganz normale einfache senden kann? Ich experimentier jetzt schon ne ganze Weile verzweifelt hier rum...:-(

    So sieht mein String momentan aus:

    Quellcode

    1. {""ID"":3,""Alarm:"""",""Info:""P 1379; FA 23596 Soll:157500 / Ist:67164"",""Pcurr:""77,""TS:""07.07.2020 09:02:49""}


    Ich hab's jetzt z.B. damit versucht:

    Quellcode

    1. jsonStr = Json.JsonSerializer.Serialize(jsonStr, jsonStr.GetType)


    Das ergibt aber gleich wieder einen "escapten" String den .NET auch wieder nicht interpretieren kann.

    Das kann doch eigentlich gar nicht so schwer sein... :(
    So ein ähnliches Replace hab ich schon versucht - allerdings mit 4 bzw. 2 Anführungszeichen - Hochkommas nimmt VB nicht ;)
    Das Ergebnis von dem Replace ist das dass gar kein Anführungszeichen mehr da ist - EINS brauch ich aber ;-(((
    Wieder die Frage, wo kommt das JSON her? Es ist nämlich komplett deformiert.
    Hier mal was ich gemacht habe:
    zunächst mal dein Json "formatiert":

    JSON-Quellcode

    1. {
    2. ""ID"":3,
    3. ""Alarm:"""",
    4. ""Info:""P 1379; FA 23596 Soll:157500 / Ist:67164"",
    5. ""Pcurr:""77,
    6. ""TS:""07.07.2020 09:02:49""
    7. }


    Was hier auffällt, ist, dass die " direkt schonmal falsch gesetzt sind und kein valides JSON erzeugen. Abgesehen von ID, sind alle Namen nicht korrekt mit " versehen. Deswegen zeigt auch ein Replace nicht die korrekte Wirkung:

    JSON-Quellcode

    1. {
    2. "ID":3,
    3. "Alarm:"",
    4. "Info:"P 1379; FA 23596 Soll:157500 / Ist:67164",
    5. "Pcurr:"77,
    6. "TS:"07.07.2020 09:02:49"
    7. }


    Mit etwas händischer Korrektur sieht das ganze dann so aus:

    JSON-Quellcode

    1. {
    2. "ID":3,
    3. "Alarm":"",
    4. "Info":"P 1379; FA 23596 Soll:157500 / Ist:67164",
    5. "Pcurr":"77",
    6. "TS":"07.07.2020 09:02:49"
    7. }


    was dann mithilfe von json2csharp.com/ und converter.telerik.com/ in eine Klasse umgewandelt werden kann:

    VB.NET-Quellcode

    1. Public Class Root
    2. Public Property ID As Integer
    3. Public Property Alarm As String
    4. Public Property Info As String
    5. Public Property Pcurr As String
    6. Public Property TS As String
    7. End Class


    Und du einfach deserialisieren kannst:

    VB.NET-Quellcode

    1. Dim json As String = File.ReadAllText("TextFile1.txt")
    2. json = json.Replace("""""", """")
    3. 'some magic to make the invalid json valid
    4. Dim test As Root = System.Text.Json.JsonSerializer.Deserialize(Of Root)(json)


    Was du nun also tun musst, sofern du auf die Quelle keinen Einfluss hast, ist das Json so umformatieren, dass es vom deserializer erkannt wird.
    Dennoch die Frage, wo kommt das JSON her?
    Den bisherigen JSON-String setze ich selbst zusammen. Dass da momentan zwischendrin noch paar Anführungszeichen an der falschen Stelle stehen weiß ich - geschenkt!
    Ich brauche den auch nicht deserialisiert sondern eben serialisiert. Und dafür brauche ich eben einfache Anführungszeichen im String!
    Hast du mal getestet was mit "Replace("""""", """")" passiert? Ich verstehe nicht was das den Replace-Befehl interessiert, ob die doppelten Anführungszeichen nun (richtig) vor oder (falsch) nach dem Doppelpunkt stehen...?
    Händisch habe ich den String auch so hinbekommen dass das funktioniert - eben mit einfachen Anführungszeichen so wie du das auch gemacht hast. Aber programmtechnisch setzt VB da immer entweder 2 oder gar keins :(
    Alternativ kannst du dir auch über Nuget NewtonSoft.JSON laden und dann wie folgt vorgehen:

    VB.NET-Quellcode

    1. Imports Newtonsoft.Json
    2. Public Class JSONExample
    3. Private JSONFile As New JSONExampleFile
    4. Private Sub BtnSerialize_Click(sender As Object, e As EventArgs) Handles BtnSerialize.Click
    5. Dim AktivDate As Date = Date.Now
    6. Dim JFILE As New JSONExampleFile
    7. JFILE.ID = 3
    8. JFile.Alarm = ""
    9. JFile.Info = "P 1379; FA 23596 Soll:157500 / Ist:67164"
    10. JFile.Pcurr = "77"
    11. JFILE.TS = String.Concat(AktivDate.ToShortDateString, " ", AktivDate.ToShortTimeString)
    12. TxtJSONOutput.Text = JSONSerialize(JFILE)
    13. End Sub
    14. Private Sub BtnDeserialize_Click(sender As Object, e As EventArgs) Handles BtnDeserialize.Click
    15. JSONFile = JSONDeserialize(TxtJSONOutput.Text)
    16. End Sub
    17. Private Function JSONSerialize(ByVal JFile As JSONExampleFile) As String
    18. Return JsonConvert.SerializeObject(JFile, Formatting.Indented)
    19. End Function
    20. Private Function JSONDeserialize(ByVal JString As String) As JSONExampleFile
    21. Return TryCast(JsonConvert.DeserializeObject(JString, GetType(JSONExampleFile)), JSONExampleFile)
    22. End Function
    23. End Class
    24. Public Class JSONExampleFile
    25. Public Property ID As Integer
    26. Public Property Alarm As String
    27. Public Property Info As String
    28. Public Property Pcurr As String
    29. Public Property TS As String
    30. End Class


    EDIT: Deserialisierung ergänzt


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Yanbel“ ()

    DANKE - die Newtonsoft.JSON hat's gebracht - allerdings mit "Formatting.None". Bei .Intended schreibt er vbCrLf's mit rein die der Webserver natürlich nicht versteht.

    Ich hatte das mit dem Serialisieren des Objects bereits mit dem System.Text.Json versucht was aber offensichtlich mit einem Object gar nichts anfangen kann.

    Vielen Dank - ich komme weiter...

    EaranMaleasi schrieb:

    .... warum kümmerst du dich nicht darum, dass das korrekt passiert?


    Irgendwie hast du mich echt nicht verstanden... ;) Hab mich doch drum gekümmert diese dämlichen doppelten Anführungszeichen wegzubekommen...

    Aber egal - das Newtonsoft.JSON-Packet hat's ja jetzt gelöst

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „EaranMaleasi“ ()

    Ja, klar.

    VB.NET-Quellcode

    1. Public Structure MaschInfo
    2. Dim ID As Byte
    3. Dim Alarm As String
    4. Dim Info As String
    5. Dim Pcurr As Double
    6. Dim TS As String
    7. End Structure
    8. Function SendToWebServer(data As MaschInfo) As Boolean
    9. Dim retwert = False
    10. Dim response As WebResponse
    11. Dim result As String = ""
    12. Dim jsonStr As String = JsonConvert.SerializeObject(data, Formatting.None)
    13. Dim oWeb As WebRequest = WebRequest.Create("https://localhost:5001/api/MaschInfos")
    14. oWeb.Method = "POST"
    15. oWeb.ContentType = "application/json; charset=UTF-8"
    16. Dim bytes As Byte() = System.Text.Encoding.ASCII.GetBytes(jsonStr)
    17. oWeb.ContentLength = bytes.Length
    18. Dim writer As Stream = oWeb.GetRequestStream()
    19. writer.Write(bytes, 0, bytes.Length)
    20. Try
    21. response = oWeb.GetResponse()
    22. Dim reader As StreamReader = New StreamReader(response.GetResponseStream)
    23. result = reader.ReadToEnd()
    24. retwert = True
    25. Finally
    26. 'frmMasch.Invoke(Sub() frmMaschinen.statusLblTCP.Text = "Datenübertragung " & result)
    27. End Try
    28. Return retwert
    29. End Function


    wenn's hilft...;-)
    Vorneweg, keine Ahnung was du oben für ein Problem beschrieben hast, doch ich sehe nicht, wie JSON.NET hier etwas tut, was System.Text.Json nicht auch könnte:

    C#-Quellcode

    1. class Program
    2. {
    3. static void Main(string[] args)
    4. {
    5. MaschInfo info = new MaschInfo
    6. {
    7. ID = 3,
    8. Alarm = string.Empty,
    9. Info = "P 1379; FA 23596 Soll:157500 / Ist:67164",
    10. Pcurr = 77,
    11. TS = "07.07.2020 09:02:49"
    12. };
    13. string json = JsonSerializer.Serialize(info, new JsonSerializerOptions { WriteIndented = true });
    14. string otherJson = Newtonsoft.Json.JsonConvert.SerializeObject(info, Newtonsoft.Json.Formatting.Indented);
    15. Console.WriteLine(json);
    16. Console.WriteLine(otherJson);
    17. Console.WriteLine();
    18. json = JsonSerializer.Serialize(info, new JsonSerializerOptions { WriteIndented = false });
    19. otherJson = Newtonsoft.Json.JsonConvert.SerializeObject(info, Newtonsoft.Json.Formatting.None);
    20. Console.WriteLine(json);
    21. Console.WriteLine(otherJson);
    22. Console.ReadKey(true);
    23. }
    24. }
    25. public class MaschInfo
    26. {
    27. public byte ID { get; set; }
    28. public string Alarm { get; set; }
    29. public string Info { get; set; }
    30. public double Pcurr { get; set; }
    31. public string TS { get; set; }
    32. }

    Hat folgenden Output:

    JSON-Quellcode

    1. {
    2. "ID": 3,
    3. "Alarm": "",
    4. "Info": "P 1379; FA 23596 Soll:157500 / Ist:67164",
    5. "Pcurr": 77,
    6. "TS": "07.07.2020 09:02:49"
    7. }
    8. {
    9. "ID": 3,
    10. "Alarm": "",
    11. "Info": "P 1379; FA 23596 Soll:157500 / Ist:67164",
    12. "Pcurr": 77.0,
    13. "TS": "07.07.2020 09:02:49"
    14. }
    15. {"ID":3,"Alarm":"","Info":"P 1379; FA 23596 Soll:157500 / Ist:67164","Pcurr":77,"TS":"07.07.2020 09:02:49"}
    16. {"ID":3,"Alarm":"","Info":"P 1379; FA 23596 Soll:157500 / Ist:67164","Pcurr":77.0,"TS":"07.07.2020 09:02:49"}


    Achja, noch etwas: warum benutzt du Encoding.ASCII? Wäre Encoding.UTF8(der Standard) nicht besser? Oder versteht die Gegenstelle nur ASCII?

    EaranMaleasi schrieb:

    ... ich sehe nicht, wie JSON.NET hier etwas tut, was System.Text.Json nicht auch könnte:

    wie auch immer - ich hab mit "JsonSerializer.Serialize(info)" nur "{}" als Ausgabe erhalten...


    Achja, noch etwas: warum benutzt du Encoding.ASCII? Wäre Encoding.UTF8(der Standard) nicht besser? Oder versteht die Gegenstelle nur ASCII?

    Da hast du Recht. Hatte ich erstmal per C&P so übernommen - hatte ich aber mittlerweile schon geändert.

    EaranMaleasi schrieb:

    ... ich sehe nicht, wie JSON.NET hier etwas tut, was System.Text.Json nicht auch könnte:


    Du meinst abgesehen davon, dass json.NET doppelt so performant ist :D
    Nein ich geb dir recht. Wenn man System.Text.Json korrekt verwendet, dann hat man genau das gleiche Ergebnis... nur halt ein bisschen langsamer (Was aber wnn wir ehrlich sind auch erst bei so 20 MB großen Dateien wirklich auffällt).


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.

    Yanbel schrieb:

    Du meinst abgesehen davon, dass json.NET doppelt so performant ist :D

    kannst Du das belegen? Das, was ich bisher gelesen habe[1], deutet darauf hin, dass System.Text.Json performanter ist.

    Grüße ... Peter

    [1]: michaelscodingspot.com/the-bat…erializers-in-net-core-3/

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „EaranMaleasi“ ()

    Sorry mein Fehler, hab mir die Quelle nochmal angeschaut und der Vergleich ging nicht gegen System.Text.Json sondern gegen den Vorgänger DataContractJsonSerializer. Mein Fehler.

    Die Vorteile von Newtonsoft gegenüber System.Text.Json hat Microsoft hier selber zusammengefasst, falls dich das interessiert. Ansonsten hier eine kurze Zusammenfassung: Über die Funktionalitäten brauchen wir nicht sprechen. System.Text.json bietet nicht einmal ansatzweise den Funktionsumfang den Newtonsoft bietet, abgesehen, von den Kernfunktionen. Tatsächlich scheint der System.Text.Json-Serializer performanter zu sein, weil er strikter arbeitet. Die beiden unterscheiden sich offenbar im Verhalten, was Fehleranfälligkeit angeht, da NewtonSoft wesentlich flexibler in der Handhabung von Daten ist als System.Text.Json. Newtonsoft ist z.B. nicht case-sensitive bei der Berücksichtigung der PropertyNames während Text.System.Json strikt das Mapping von PropertyNames ablehnt, die nicht exakt gleich geschrieben sind. Das liefert den Hauptunterschied in der Performance, da Microsoft an dieser Stelle auf einen exakten (schnelleren) Abgleich der Namen setzt und Newtonsoft hier toleranter ist und jegliche Schreibweise akzeptiert. Dies kann über eine globale Variable in Text.System.Json abgeschaltet werden, womit die Serialisierer wieder bei gleicher Performance sind.


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.
    Json.NET ist das schweizer Multifunktionstaschenmesser mit Wasserkocher, Solarzelle, und E-Roller, was Json angeht. Dem steht nichts außer Frage.
    Aber warum für einen so minimalistischen Job, wie den oben, mir eine gewaltige Library einbinden, wenn das Framework für mich bereits alles liefert was ich brauche.

    Ein paar Jahre zurück hätte (und habe) ich ebenfalls jedem Empfohlen für alles was Json angeht Json.NET einzubinen, da es keine bessere alternative gab. Jetzt jedoch, wo sich Microsoft einiges von Json.NET abgeguckt hat, würde ich jederzeit zuerst System.Text.Json empfehlen, bevor man die großen Geschütze auffährt.

    Am Ende des Tages ist es jedoch recht egal was man nutzt. Zugriffs- und Lesezeiten sind dank SSDs so klein wie noch nie, und Speicherkapazitäten wachsen durch die Wolken. Da kommt es auf ein paar hundert Kilobyte mehr oder minder auch nicht an.

    Ich wollte oben auch lediglich beweisen, dass das Problem nicht durch System.Text.Json entstanden ist, und sehr wohl für die Aufgabenstellung des TE's benutzt werden kann.
    Ich wollte keines Wegs damit sagen, dass System.Text.Json in allen belangen so gut, oder gar besser wäre als Json.NET. Ich bin mir der Limitierungen sehr bewusst.
    @EaranMaleasi
    Da kann ich uneingeschränkt zustimmen. Wobei wir ergänzend dazu bei den kleinen Datenmengen über die wir hier reden, sowieso mal gar keinen Unterschied feststellen, was die Performance angeht. Ich hab mich heute tatsächlich das erste mal richtig mit System.Text.Json auseinander gesetzt, denn als Microsoft das implementiert hat, hab ich den fälschlicherweise direkt in eine Schublade mit dem DataContractJsonSerializer geschmissen und mir gedacht: Wozu was ändern, ich bin mit Json.Net doch rundum zufrieden. Dementsprechend habe ich auch mein Beispiel auf json.Net darauf aufgebaut. Zukünftig werde ich wohl hinsichtlich der Performance-Unterschiede doch mal abwägen, ob ich nicht an der einen oder anderen Stelle vielleicht doch wieder auf die Framework-Komponenten zurückgehe.

    Aber da Json.Net in der Standardkonfiguration deutlich flexibler ist, denke ich, dass der TE an dieser Stelle auch nichts falsch gemacht hat, wenn er, gerade auch in Hinblick auf Schnittstellenkompatibilität,Webservices und APIs, einen weniger strikten Serializer nutzt. Spielt zwar letzlich nur für die Deserialisierung eine Rolle, aber wir kennen ja auch den kompletten Projektumfang nicht.

    Fazit: Lösung ist da, der TE ist glücklich und der Thread kann geschlossen werden.


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.