Funktionen rund um JSON-Strings: obj2json() und json2obj().
Das Modul hat versteckte Attribute. Damit diese aktiv übernommen werden reicht es nicht aus, den Code in ein neues Modul zu kopieren. Man muss das Modul aus der Datei nach VBA importieren.
Bild zum Import
Für mehrere Projekte brauche ich JSON. Ich arbeitete bisher mit VB-JSON. Aber irgendwie störte es mich, dafür jeweils 2 Klassen und ein Modul zu kopieren. Bei der Analyse des Codes war ich erstaunt, dass er ohne Reguläre Ausdrücke arbeitet.
Darum setzte ich mich mal hin, eine eigene Version zu erstellen. Messungen haben ergeben, dass beide etwa gleich schnell sind.
Ich versuchte mich möglichst nahe an JavaScript Object Notation hinzukommen. Nur wenn man beim JSON erstrellen den Parameter jqmInternalArrayPrefix mitgibt, kommen TypenPrefixe vor die [] um zu definieren ob es sich um ein Array oder eine Collection handelt
Public Function obj2json( _ ByRef iObj As Variant, _ Optional ByVal iEncodeParams As jsonEncodeParams = jqmDefault _ ) As String
Gibt ein JSON-String zurück
Public Function json2obj( _ ByVal iString As Variant, _ Optional ByVal iParams As jsonDecodeParams = jrtDefault, _ Optional ByRef oObj As Variant) As Variant
Ein Dictionary-, Collection-Object oder ein Variant-Array
Einstellung, ob Strings im JSON in ' oder in “ gefasst werden sollen
Public Enum jsonEncodeParams jqmDoubleQuote = 2 ^ 1 'Umfasst die Values mit einem " jqmSingleQuote = 2 ^ 2 'Umfasst die Values mit einem ' jqmForceObject = 2 ^ 3 'Wandelt Arrays in Objekte (Dictionaries) jqmInternalArrayPrefix = 2 ^ 4 'Der JSON-String wird mit eigenen Prefixen bei Array und Collection mitgeliefert jqmReverseSolidusAsUnicode = 2 ^ 5 'Ein \ in einem String wird nicht als \\ sondern als Unicode gaparst jqmNoErrorForWrongType = 2 ^ 6 'Wenn ein nicht parsbarer Wert kommt, den TypeName() ausgeben jqmDefault = jqmDoubleQuote End Enum
Einstellungen, ob […] in ein Array oder in eine Collection geschrieben werden soll
Public Enum jsonDecodeParams jrtCollection = 2 ^ 1 'Als Collection jrtArray = 2 ^ 2 'Als Array jrtDictionary = 2 ^ 3 'Als Dictionary jrtNotCastValue = 2 ^ 4 'cast der Values verhindern jrtEmptyList = 2 ^ 5 'Angabe, ob bei einem Leeren String eine Collection/Array/Dictionary zurückgegeben werden soll jrtSingle2List = 2 ^ 6 'Parst ein einzelnesItem zu einer Liste jrtDefault = jrtArray End Enum
Hier einige Anwendungsbeispiele
Für die Ausgabe der Resultate verwendete ich die Funktion [VBA] print_r().
'1) Einfacher Array print_r obj2json(array(1,2,3)) <String> '[1,2,3]'
'2a) Array mit Texten und doppelten Anführungszeichen print_r obj2json(array("a","b","c")) <String> '["a","b","c"]' '2b) Dito mit einfachen Anführungszeichen print_r obj2json(array("a","b","c"), jqmSingleQuote) <String> '['a','b','c']'
Public Sub testObj2Json() Dim c As New Collection Dim d As New Dictionary c.add True 'Boolen-Wert c.add Array(1, 2, 3) 'Normaler Zehlenarray d.add "t1", "a" & vbTab & "b" 'Text mit Tabulator d.add "t2", "a¦'b':{1....n}" 'Text mit Sonderzeichen, ' und {} c.add d c.add Null 'Null c.add Now 'Datum/Urhzeit Debug.Print "'Object" print_r c 'Ganze Collection c anzeigen Debug.Print "'JSON-String" print_r obj2json(c, jqmSingleQuote) Set d = Nothing Set c = Nothing End Sub
Und die Ausgabe davon
'Object <Collection> ( [1] => <Boolean> True [2] => <Variant()> ( [0] => <Integer> 1 [1] => <Integer> 2 [2] => <Integer> 3 ) [3] => <Dictionary> ( [t1] => <String> 'a\tb' [t2] => <String> 'a¦'b':{1....n}' ) [4] => <Null> [5] => <Date> 26.11.2014 12:37:03 ) 'JSON-String <String> '[true,[1,2,3],{'t1':'a\u0009b','t2':'a\u00A6\u0027b\u0027:{1....n}'},null,2014-11-26T12:37:03]'
Und alles wieder zurück
'Als Array print_r json2obj("[1,2,3]") <Variant()> ( [0] => <Byte> 1 [1] => <Byte> 2 [2] => <Byte> 3 ) 'Als Collection print_r json2obj("[1,2,3]", jrtCollection) <Collection> ( [1] => <Byte> 1 [2] => <Byte> 2 [3] => <Byte> 3 )
'2a) Array mit Texten und doppelten Anführungszeichen print_r json2obj("[""a"",""b"",""c""]") <Variant()> ( [0] => <String> 'a' [1] => <String> 'b' [2] => <String> 'c' ) '2b) Dito mit einfachen Anführungszeichen print_r json2obj("['a','b','c']") <Variant()> ( [0] => <String> 'a' [1] => <String> 'b' [2] => <String> 'c' )
print_r json2obj("[true,[1,2,3],{'t1':'a\tb','t2':'a\u00A6\'b\'\:{1....n}'},null,'2014-02-24T11:11:41']") <Variant()> ( [0] => <Boolean> True [1] => <Variant()> ( [0] => <Byte> 1 [1] => <Byte> 2 [2] => <Byte> 3 ) [2] => <Dictionary> ( [t1] => <String> 'a\tb' [t2] => <String> 'a¦'b'\:{1....n}' ) [3] => <String> 'null' [4] => <Date> 24.02.2014 11:11:41 )
Ich verwende in diesem Beispiel die Funkionen [VBA] cDict() und [VBA] cCollection() im ein Dictionary bzw. eine Collection zu erstellen.
'Normaler cast print_r obj2json(cCollection(1,"c",cDict("b",array(1,2)))) <String> '[1,"c",{"b":[1,2]}]' 'Mit jqmInternalArrayPrefix print_r obj2json(cCollection(1,"c",cDict("b",array(1,2))), jqmInternalArrayPrefix) <String> '#C[1,'c',{'b':#A[1,2]}]' 'Und die Rückwandlung ohne den Prefix. Beachte, aus dem ursprünglichen Collection wurde ein Array print_r json2obj("[1,'c',{'b':[1,2]}]") <Variant()> ( [0] => <Byte> 1 [1] => <String> 'c' [2] => <Dictionary> ( [b] => <Variant()> ( [0] => <Byte> 1 [1] => <Byte> 2 ) ) ) 'Und mit PRefixen wird der Richtige Listentyp wieder hergestellt print_r json2obj("#C[1,'c',{'b':#A[1,2]}]") <Collection> ( [1] => <Byte> 1 [2] => <String> 'c' [3] => <Dictionary> ( [b] => <Variant()> ( [0] => <Byte> 1 [1] => <Byte> 2 ) ) )
Wenn der übergeben String kein JSON-String ist, gibt es verschiedene Möglichkeiten
'Standard: Es wird kein Objekt erstellt print_r json2obj("abc") <Empty> 'String in ein Array parsen print_r json2obj("abc", jrtSingle2List) <Variant()> ( [0] => <String> 'abc' ) 'String in ein Dictionary parsen print_r json2obj("abc", jrtSingle2List + jrtDictionary) <Dictionary> ( [0] => <String> 'abc' )
Normalerweise werdend ie Werte in passende Typen umgewandelt
print_r json2obj("[Null,True,12.3]") <Variant()> ( [0] => <Null> [1] => <Boolean> True [2] => <Double> 12.3 )
Mittels jrtNotCastValue kann dies aber auch unterbunden werden
print_r json2obj("[Null,True,12.3]", jrtNotCastValue) <Variant()> ( [0] => <String> 'Null' [1] => <String> 'True' [2] => <String> '12.3' )
print_r json2obj(null) <Empty> print_r json2obj(null,jrtEmptyList) <Variant()> () print_r json2obj(empty,jrtEmptyList) <Variant()> () print_r json2obj("[1]",jrtEmptyList) <Variant()> ( [0] => <Byte> 1 )