Besonders bei umfangreichen JSON - Strukturen ist es aufwändig, eine passende ABAP Struktur zu erstellen. Hier kann der Report /EPO1/JSON_GENERATE_ABAP helfen. Erzeugt wird eine Typdefinition in Sourcecode, die wahlweise in einem Report, Funktionsbaustein oder Klasse hinterlegt und verwendet werden kann.
Bei der Verwendung als Funktionsbaustein - Parameter empfiehlt es sich, den Code in der PUBLIC - Sektion einer Z-Klasse zu hinterlegen.
Für die Verwendung in einem JSON - Webservice ist ev. auch ein Mapping in der Tabelle /EPO1/FIELD_MAP notwendig; optional kann dieses Mapping auch gleich erzeugt werden (ab Version 4.9.3 verfügbar).
Voraussetzung ist eine JSON - Datei, die alle gewünschten Felder/Strukturen/Tabellen enthält, wobei bei den Tabellen möglichst immer nur eine Zeile mit allen zu erwartenden Inhalten befüllt sein soll. D.h. wenn entweder Nutzdaten oder eine Fehlermeldung zu übertragen sind, dann müssen sowohl die Nutzdaten als auch die Fehlermeldung in der JSON - Datei enthalten sein.
Hinweis: die generierte Struktur kann jederzeit manuell korrigiert/ergänzt werden, aber eine sauber vorbereitete JSON - Datei vermeidet bzw. verringert die notwendige Nacharbeit.
Beispiel - Fehlermeldung
{
"error":"error description.."
}
Beispiel - Nutzdaten
{
"customer":
{
"name":"Hinkel und Stein",
"email":"hinkel@stein.com"
}
}
Beispiel - Gesamtstruktur (künstlich zusammengeführt)
{
"customer":
{
"name":"Hinkel und Stein",
"email":"hinkel@stein.com"
},
"error":"error description.."
}
Daraus kann eine ABAP Struktur generiert werden, die sowohl Platz für die Nutzdaten als auch für die Fehlermeldung enthält.
Wenn in einer Tabelle mehrere Zeilen enthalten sind, soll nur eine davon behalten werden, wobei hier ebenfalls eine möglichst umfangreiche Struktur erstellt werden soll (falls die die Tabellenzeilen in ihren Strukturen unterscheiden)
Beispiel - mehrere Zeilen mit unterschiedlichen Strukturelementen
{
"customers":
[
{
"name":"Hinkel und Stein",
"email":"hinkel@stein.com"
},
{
"name":"Rast und Ruh",
"telephone":"01/23456789"
}
]
}
Beispiel - Zusammenfassung auf nur 1 Zeile mit allen vorkommenden Strukturelementen
{
"customers":
[
{
"name":"Hinkel und Stein",
"email":"hinkel@stein.com", // Strukturelement aus der ersten Zeile
"telephone":"01/23456789" // Strukturelement aus der zweiten Zeile
}
]
}
Start des Reports /EPO1/JSON_GENERATE_ABAP über die Transaktion SE38 oder SE80;
Selektionsschirm:
Im ersten Block wird die Art des Webservices (Service Provider / Service Konsument) und die Richtung (ein-/ausgehend, Request/Response) festgelegt. Der ‘Service Name Identifier’ wird für das Mapping der Feldnamen verwendet. Wenn kein Feldmapping erzeugt werden soll, kann dieser Parameter leer bleiben.
Der zweite Block selektiert die JSON - Datei, die analysiert werden soll.
Der dritte Block definiert das Default-Mapping zwischen JSON - Feldnamen und den ABAP Elementnamen. Aufgrund dieser Einstellung (gemeinsam mit dem Service Name Identifier) wird die Mappingtabelle /EPO1/FIELD_MAP befüllt (das ist ein optionaler Schritt nach der Verarbeitung). Hier empfiehlt es sich, möglichst Rücksicht auf die verwendete Schreibweise im JSON zu nehmen (damit möglichst wenige Feldnamen ein explizites Mapping erfordern).
Nach dem Start mit F8 wird die JSON - Datei analysiert und ein Vorschlag für das Mapping (Typnamen, Feldnamen) erstellt. Dieses kann nun nach Bedarf nachgebessert werden.
Feldnamen, die zu lange geraten, werden entsprechend gekürzt und bei gleichnamigen Kürzungen entsprechend durchnumeriert.
Die hier verwendete JSON - Datei enthält Strings (Zeichenketten), Zahlen, Boolean, Tabelle und Struktur.
Beispiel - JSON
{
"Zahl":1,
"FloatIng": 1.23,
"StringEnt":"Teststring",
"WahrLich":false,
"Struct":
{
"Nummer":2,
"Char":"test"
},
"Table":
[
{
"Street":"Rennweg",
"Nummer":73
}
],
"Ende":true
}
Im Ergebnis schaut der Vorschlag dann so aus:
Der linke Teil zeigt die JSON - Namen, so wie sie erkannt wurden. In den rechten beiden Spalten kann der ABAP Feldname und der vorgeschlagene Typ noch geändert werden. Ein Druck auf 'Create type definition' generiert den dazupassenden Sourcecode und kopiert ihn in die Zwischenablage. Zur Hilfestellung beim Programmieren werden die original JSON Feldnamen in Kommentar angeschrieben.
Beispiel - ABAP Typdefinition:
TYPES:
BEGIN OF ty_request_struct_s,
nummer TYPE i, " Nummer
char TYPE string, " Char
END OF ty_request_struct_s.
TYPES:
BEGIN OF ty_request_table_s,
street TYPE string, " Street
nummer TYPE i, " Nummer
END OF ty_request_table_s.
TYPES:
ty_request_table_t TYPE STANDARD TABLE OF ty_request_table_s WITH DEFAULT KEY
TYPES:
BEGIN OF ty_request_s,
zahl TYPE i, " Zahl
float_ing TYPE float, " FloatIng
string_ent TYPE string, " StringEnt
wahr_lich TYPE xsdboolean, " WahrLich
struct TYPE ty_request_struct_s, " Struct
table TYPE ty_request_table_t, " Table
ende TYPE xsdboolean, " Ende
END OF ty_request_s.
Nun können Daten für diesen Typ angelegt, befüllt und über ein JSON Webservice versendet/empfangen werden.
In der ALV - Ansicht können vorgeschlagene Typnamen manuell geändert werden. Wenn der Name eines existierenden Data-Dictionary-Typs verwendet wird (oder ein öffentlich sichtbarer Typ einer Klasse), wird dieser Typ als 'bereits vollständig definiert' betrachtet. Das bedeutet, daß für sämtliche untergeordneten Elemente kein Code generiert wird.
Beispiel - der Type für 'Struct' wurde durch einen öffentlich sichtbaren Klassen-Typ ersetzt, die Struktur für die Tabelle durch eine Data-Dictionary - Struktur:
Von beiden Typen wird erwartet, daß sie korrekt definiert und aktiviert sind, sowie daß sie die benötigten Felder enthalten.
Z.B. der Typ ZCL_STRUCT=>TY_STRUCT muß/soll die Felder NUMMER und CHAR enthalten, der Typ Z_TEST_STRUCT die Felder STREET und NUMMER.
Ein Anwendungsfall könnte eine gemeinsam genutzte Struktur sein, die in mehreren JSON - Schnittstellen gleichermaßen zum Einsatz kommt, bzw. eine Teilstruktur, die in einer JSON - Schnittstelle an verschiedenen Stellen öfters verwendet wird. Es wird empfohlen, die Definition solcher gemeinsam genutzter Typen in den öffentlichen Teil einer globalen Klasse zu stellen.
Wenn das Service im Selektionsschirm eingegeben wurde, kann auch das Feldmapping erstellt werden. Gemäß dem gewählten Default-Mapping werden hier nur jene Feldnamen eingetragen, die ein explizites Mapping benötigen:
Nach einer erfolgreichen Analyse wird das vorgeschlagene Feldmapping angezeigt:
Falls bestehende Einträge überschrieben werden, zeigt die Ampel ein gelbes Licht:
Vor dem eigentlichen Schreiben erfolgt noch eine Abfrage (Dialog), wenn Daten überschrieben werden, folgt ein zweiter Dialog. Anschließend können die Änderungen in einen Customizing-Transport übernommen werden.