User Tools

Site Tools


vba:cast:json

[VBA] JSON

Funktionen rund um JSON-Strings: obj2json() und json2obj().

Version 2.9.1 16.01.2020
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

Download lib_json.bas (V-2.9.1)

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

Definition

obj2json

Public Function obj2json( _
    ByRef iObj As Variant, _
    Optional ByVal iEncodeParams As jsonEncodeParams = jqmDefault _
) As String

Parameterliste

  • iObj Das Objekt (Dictionary, Collection, Array), welches in ein JSON-String geschrieben werden soll
  • iEncodeParams Angabe, was für einAnführungszeichen verwendet werden soll

Return

Gibt ein JSON-String zurück

json2obj

Public Function json2obj( _
    ByVal iString As Variant, _
    Optional ByVal iParams As jsonDecodeParams = jrtDefault, _
    Optional ByRef oObj As Variant) As Variant

Parameterliste

  • iString JSON-String, der geparst werden soll
  • iParams Steuert, ob […] als Array oder als Collection zurückgegeben wird
  • oObj das geparste Objekt, analog zurm Returnvalue. Auf diese Art muss man den Return-Wert nicht zuerst prüfen ob es ein Array oder ein Object ist

Return

Ein Dictionary-, Collection-Object oder ein Variant-Array

Enumerator

jsonEncodeParams

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

jsonDecodeParams

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

Anwendungsbeispiele

Hier einige Anwendungsbeispiele

Für die Ausgabe der Resultate verwendete ich die Funktion [VBA] print_r().

obj2json

1) Ein Einfacher Zahlenarray

'1) Einfacher Array
print_r obj2json(array(1,2,3))
<String> '[1,2,3]'

2) Einfacher Stringarray

'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']'

3) Ein komplexeres Beispiel

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]'

json2obj

Und alles wieder zurück

1) Einfaches Zahlenarray/Collection

'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
)

2) Einfacher Stringarray

'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'
)

3) Ein komplexeres Beispiel

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
)

4) Mit interner ArrayPrefix

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
        )
    )
)

5) Wenn der String kein JSON-String ist

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'
)

6) Werte Nicht Casten

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'
)

7) Leere Listen erstellen

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
)

Code

vba/cast/json.txt · Last modified: 16.01.2020 08:44:37 by yaslaw