Neuling: Probleme mit Parsing

Hallo, das ist mein erster Post hier im Forum. Ich hoffe, dass ich schnell voran komme.

Ich versuche die Antwort aus einem POST ApiCall zu verarbeiten. Aus den „responses@APICall_2“ möchte ich die Id in eine Variable schreiben, damit diese im nächsten Step nutzbar ist.

Kann mir jemand grundlegen erklären, was ich tun muss?

Danke schon mal für eure Hilfe!

Hallo @laddi,

kannst du die Response bitte einmal als Text posten. Das machts einfach ein Template zu erstellen.

Viele Grüße
Lukas

1 Like

Klar :slight_smile:

[{„Data“: {„UserSessionForInfo“: {„Email“: „user@domain.de“,„Id“: „asdfasdfasdf-28db-1234-ac4c-337e2f2465f6“,„UserID“: 123456,„UserName“: „username“}}}]

Danke @synesty-Lukas

Ich habe es inzwischen geschafft ein Template zu schreiben.

<#assign row = target.addRow()>
<#list json[„Data“][„UserSessionForInfo“] as p >
<#assign row = target.addRow()>
${addColumns(row, p, ‚‘, {‚columns‘:[‚Email‘, ‚UserID‘, ‚UserName‘], ‚mode‘:‚exclude‘})}
</#list>

Jetzt stellt sich mir die Frage, wie ich die vorhandene ID in eine Variable schreiben kann um diese dann bei anderen Flows benutzen zu können. Ein anderer Foreneintrag zeigte nur auf, dass das „so“ nicht geht. Hat sich da inzwischen was getan?

Hallo @laddi,

wollte dir gerade mit dem Template antworten. Aber hast du ja selbst hinbekommen. Mein Vorschlag hätte auch nicht viel anders ausgesehen:

<#assign row = target.addRow()>
<#list json['Data']['UserSessionForInfo'] as j >
  <#assign row = target.addRow()>
  ${addColumns(row, j)}
</#list>

Aber du excludest ja auch noch.

Auf deine andere Frage zukommen. Du kannst die eingelesenen werde in anderen Steps überall weiterverwendet, wo ein „+“ zu sehen ist. Im Mapper zum Beispiel im Wertfeld über das „+“. Dann klickst du auf Meta-Daten und dann auf den Json-Reader. Am Ende könnte dann sowas in deinem Wertfeld stehen:
image

Wichtig zu beachten ist, dass bei dir „output@JSON2Spreadsheet_3“ wahrscheinlich eine andere Nummer hat. Zudem musst du auch, wenn du im Mapper die Daten aus vorherigen Steps holst, die erweiterte Option wählen:

Viele Grüße
Lukas

1 Like

Klasse! Da bin ich nun auch einen erheblichen Schritt nach vorne gekommen.
Ich habe nun eine Liste mit Ordertoken im Datastore liegen. In der nächsten Step-Gruppe sollen nun die Orderdetails abgeholt werden. Hier scheitere ich aber.

Mein Request:
<#list spreadsheet@SpreadsheetMapper_22.getRows() as row>${row.get(„Id“)!}</#list>/Roles/Sellers/${CompanyId!}/Orders/<#list spreadsheet@SpreadsheetMapper_30.getRows() as row>${row.get(„OrderToken“)!}</#list>

Ich bekomme allerdings eine Fehlermeldung zurück, die ich nicht richtig verstehe, da der Aufbau laut API-Doku genau so sein muss.

DOKU der API
Abrufen einer Bestellung
URL: [Server]/[SessionId]/Roles/Sellers/[CompanyId]/Orders/[OrderToken]
HTTP Method GET
Parameter
Name Data type Required Description

SessionId Guid X Ihre Sitzungsnummer
CompanyId Long X Ihre Firmennummer
OrderToken Guid X Die Bestellnummer

Fehlermeldung: Step GET SingleOrder: HTTP status: 400 (Bad Request), Response Content: Bad Request <META HTTP-EQUIV=„Content-Type“ Content="text/html;

Vielleicht hast du eine Idee warum ich den 400er zurück bekomme.

LG,
Sebastian

Hallo @laddi,

welchen Step genau verwendet du um den APICall zu machen? Denn wenn du eine Liste von IDs hast, bei der du für jede ID einen einzelnen Call machen möchtest, empfehle ich dir den SpreadsheetURLDownload.

Vielleicht hilft dir der ja schon weiter.

Viele Grüße
Lukas

Das war eine gute Idee. So habe ich die Orderzeilen alle bekommen.

Jetzt kommt das nächste „Problem“. Im JSON sind Spalten enthalten, die selbst wieder eigene Verzweigungen haben. Beispielsweise BillingAddress, DeliveryAddress und OrderPositions. Diese würde ich gern in eigene Spreadsheets schreiben und als Identifier immer den OrderToken dazuschreiben.

Dazu fehlt mir allerdings jegliche Idee :smiley:

Hast du nochmal einen Input für mich? @synesty-Lukas

Hallo @laddi,

ich denke am einfachsten wäre, wenn du diese Spalten mit JSONs im selben Parsing verarbeitest und in den nächsten Mappern dann dir zurecht filterst.
Dein aktuelles Parsing kannst dann wie folgt erweitern:

${addColumns(row, p, ‚', {'columns':['BillingAddress', 'DeliveryAddress', 'OrderPositions'], 'mode':'exclude'})}

<#list p['BillingAddress'] as b>
<#assign row = target.addRow()>
${addColumns(row, b, 'BillingAddress_')}
</#list>

<#list p['DeliveryAddress'] as d>
<#assign row = target.addRow()>
${addColumns(row, d,'DeliveryAddress_')}
</#list>

<#list p['OrderPositions'] as o>
<#assign row = target.addRow()>
${addColumns(row, o, 'OrderPositions_')}
</#list>

Also erst excludest du die JSON Spalten um sie danach einzeln einzulesen und auszugeben.

Viele Grüße
Lukas

Das klingt vollkommen schlüssig, ich habe mich auch schon gewundert, warum da so viele Steps notwendig sind. Ich denke mehr Übung mit Freemarker wird das auf die Zeit bessern :wink: .

Dein template schmeißt mir einen Fehler zurück:

C-1 GET OrderList: (Root Causes: ParseException: Syntax error in template „jsonToSpreadsheet“ in line 1, column 22: Lexical error: encountered „\u201a“ (8218), after „“.)

Hallo @laddi,

also das ist nur ein Teil des Skripts, was du in die oberste #list Anweisung deines Skripts packen müsstest. Die Variable "p" war nur ein Beispiel. Kann sein dass es bei dir ganz anders benannt hast.

Hier ist es zum Beispiel "r".

Weil die Fehlermeldung sagt aus der Fehler ist in line 1 in column 22, und das müsste Skript von dir sein. :slight_smile:

Viele Grüße
Lukas

Arghs… >.< … ich check’s nicht so ganz.
An welcher Stelle würdest du das einfügen?

Step 1 holt die Orderliste ab.
Step 2 holt die einzelnen Orders in eine Spreadsheet (SpreadsheetURLdownloader)
Step 3 packt dann die einzelnen Files an und
Step 4-6 ziehen sich die einzelnen Tables raus.

Würdest du das dann anstelle des Steps 4 machen?

Ich komm mir super noobig vor, aber das gehört wohl dazu wenn man Noob ist :smiley:

Alles gut, du bist schon mega weit :slight_smile: Order-Daten sind meist die komplexesten Datenstrukturen. Da gibt es leider selten den einfachen Weg.

Könntest du hier anonymisiert folgendes zur Verfügung stellen?

  1. komplette JSON Response einer Order
  2. Eine Tabelle, mit dem gewünschten Ergebnis, wie du es brauchst?

Das würde es einfacher machen.

1 Like

Hey,
ja klar das mach ich morgen früh fertig.

Es wird noch ein wenig spannender. Der Adresssatz muss mit der Customerliste aus WooCommerce abgeglichen werden. Falls die Adresse dort vorhanden ist muss die entsprechende CustomerID in die Bestellung->WooCommerce eingefügt werden.

Ich erstelle morgen, wie gesagt, mal Beispieldaten. Das Erzeugen von WooCommerce Orders mit statischer JSON hat vorhin schon geklappt.

Lieben Dank für die Unterstützung! Das macht Laune! :upside_down_face:

Guten Morgen,
Eine anonymisierte Response habe ich hier angefügt, damit der Post einigermaßen lesbar bleibt.
response_1-anonymisiert.json (4,0 KB)

Ich habe das gleiche Problem mit dem Auslesen der Kundenliste, ich bekomme die Columns nicht umgesetzt. Hier die anonymisierte Response:
response_customer (WooCo) - anonymisiert.json (4,7 KB)

Das Parsing ist aktuell:

<#assign row = target.addRow()>
<#list json as j >
	<#assign row = target.addRow()>
	${addColumns(row, j, "", {'columns':['billing', 'shipping', 'meta_data'], 'mode':'exclude'})}
</#list>

<#list json as b >
  <#assign row = target.addRow()>
  ${addColumns(row, b['billing'], "billing_", {"autoExpand":"asRows"})}
</#list>

<#list json as d>
	<#assign row = target.addRow()>
	${addColumns(row, d['shipping'], "shipping_", {"autoExpand":"asRows"})}
</#list>

<#list json as o>
	<#assign row = target.addRow()>
	${addColumns(row, o['meta_data'], "meta_data_", {"autoExpand":"asRows"})}
</#list>

Allerdings sind dann die Spalten billing, shipping und meta_data leer. Wenn ich das so mache, wie von dir vorgeschlagen, werden die Billing-Spalten nicht angezeigt.

Wird das „as j“ überhaupt bis in den nächsten List-tag mitübernommen?

<#assign row = target.addRow()>
<#list json as j >
	<#assign row = target.addRow()>
	${addColumns(row, j, "", {'columns':['billing', 'shipping', 'meta_data'], 'mode':'exclude'})}
</#list>
<#list j['billing'] as b>
<#assign row = target.addRow()>
${addColumns(row, b, 'billing_')}
</#list>

Wenn ich die erste Liste offen lasse und erst am Ende schließe, fügt er die Spalten an, doch sind diese leer.

Hallo @laddi,

das schließende #list von #list json as j muss ganz am Ende gesetzt sein, also nach den anderen #list- Anweisungen und die beiden {} in addColumns müssen auch weg:

<#assign row = target.addRow()>
<#list json as j >
	<#assign row = target.addRow()>
	${addColumns(row, j, "", 'columns':['billing', 'shipping', 'meta_data'], 'mode':'exclude')}

<#list j['billing'] as b>
<#assign row = target.addRow()>
${addColumns(row, b, 'billing_')}
</#list>
</#list>

Viele Grüße
Lukas

Hey @synesty-Lukas,
danke für deine Nachricht!

Das mit dem #list Argument gibt total Sinn. Die {} sind allerdings in eurem Parsing-Beispiel mit dem Exclude auch enthalten. Nehme ich die raus, läuft er auf einen Fehler.

Das Parsing ist nun so:

<#assign row = target.addRow()>
<#list json as j >
	<#assign row = target.addRow()>
	${addColumns(row, j, "", {'columns':['billing', 'shipping', 'meta_data', '_links'], 'mode':'exclude'})}
	
		<#list j['billing'] as b>
	  		<#assign row = target.addRow()>
	  		${addColumns(row, b, "billing_")}
		</#list>

		<#list j['shipping'] as d>
			<#assign row = target.addRow()>
			${addColumns(row, d, "shipping_")}
		</#list>

		<#list j['meta_data'] as m>
			<#assign row = target.addRow()>
			${addColumns(row, m, "meta_data_")}
		</#list>

		<#list j['_links'] as l>
			<#assign row = target.addRow()>
			${addColumns(row, l, "_links_")}
		</#list>
	  
</#list>

Das läuft jetzt. Er fügt das zeilenversetzt ein :-), bedeutet also, dass für eine Zeile jetzt weitaus mehr Zeilen anfallen. Mal schauen, wie ich das zusammen bekomme. Danke @synesty-Lukas

Um den Zeilenversatz zu entfernen habe ich die Zeile <#assign row = target.addRow()> aus den Sublists genommen. Jetzt passt das Ergebnis erstmal und wird in den DataStore geschrieben.

Nochmal zurück zu der Orderlist vom Anfang. Diese habe ich nun mit den Erkenntnissen aus dem Verlauf hier ebenfalls auftrennen können. Nun gibt es allerdings dort innerhalb der OrderPositionlist noch eine Itemlist. Die komplette Response war diese hier: response_1-anonymisiert.json (4,0 KB)

Hier mein transformationTemplate

<#assign row = target.addRow()>
<#list json["Data"]["OrderForView"] as ofv >
	<#assign row = target.addRow()>
	${addColumns(row, ofv, "", {'columns':['BillingAddress', 'DeliveryAddress', 'OrderPositionList'], 'mode':'exclude'})}
	
		<#list ofv['BillingAddress'] as b>
        	${addColumns(row, b, "BillingAddress_")}
		</#list>

		<#list ofv['DeliveryAddress'] as d>
			${addColumns(row, d, "DeliveryAddress_")}
		</#list>

		<#list ofv['OrderPositionList'] as m>
			${addColumns(row, m, "OrderPositionlist_")}
         </#list>
</#list>

Die OrderPositionList\Items möchte ich so auftrennen, dass pro Artikel eine Zeile entsteht.
Wichtig ist dabei nur, dass noch der Ordertoken eine Spalte hat; damit später richtig zugeordnet werden kann.

Die aktuelle Response in der Spalte „OrderPositionlist_Items“ sieht so aus

{
„DiscountAmount“: 0,
„DiscountRate“: 0,
„IndexId“: 1,
„NumberOfWithdrawals“: 2,
„OfferSourceId“: 1,
„OrderAmount“: 3,
„OrderQuantity“: 3,
„PackType“: „“,
„ParentProductEntityTypeId“: 7,
„ParentProductId“: 600574,
„ProductEntityTypeId“: 8,
„ProductId“: 872647,
„ProductName“: „Beispielprodukt1“,
„ProductSourceId“: 1,
„Remark“: „“,
„SKU“: „12345“,
„TotalAmount“: 300,
„TotalPrice“: 51.18,
„TotalValueOfGoods“: 51.18,
„UnitOfMeasure“: „ml“,
„UnitPrice“: 17.06,
„UnitPriceList“: 17.06,
„VatType“: 1,
„WithdrawalQuantity“: 50
}, {
„DiscountAmount“: 0,
„DiscountRate“: 0,
„IndexId“: 2,
„NumberOfWithdrawals“: 1,
„OfferSourceId“: 1,
„OrderAmount“: 1,
„OrderQuantity“: 1,
„PackType“: „“,
„ParentProductEntityTypeId“: 7,
„ParentProductId“: 1027349,
„ProductEntityTypeId“: 8,
„ProductId“: 1027350,
„ProductName“: „Beispielprodukt2“,
„ProductSourceId“: 1,
„Remark“: „“,
„SKU“: „23456“,
„TotalAmount“: 1,
„TotalPrice“: 164.79,
„TotalValueOfGoods“: 164.79,
„UnitOfMeasure“: „Stck.“,
„UnitPrice“: 164.79,
„UnitPriceList“: 164.79,
„VatType“: 1,
„WithdrawalQuantity“: 1
}

Hat jemand Vorschläge dazu?

Guten Morgen allerseits und einen guten Start in die neue Woche!

Wenn ich das hinzufüge, schreibt er leere Zeilen mit jedem einzelnen Artikel unter die Auftragskopfzeile.

        <#list ofv['OrderPositionList']['Items'] as itm>
          <#assign row = target.addRow()> 
          ${addColumns(row, itm, "Items_")}
        </#list>

Ich habe nun versucht die Tabelle in Kopf- (Master) und Positionsdaten (Child) zu trennen. Leider fehlt aber auch hier der Order_Token als master_identifier, da er in den ursprünglichen Zeilen unterhalb der Kopfdaten schon nicht enthalten ist. Ich habe versucht das über Filter und ColumnCombiner abzubilden, ohne Erfolg. Hier das aktuelle transformationTemplate

<#assign row = target.addRow()>
<#list json["Data"]["OrderForView"] as ofv >
	<#assign row = target.addRow()>
	${addColumns(row, ofv, "", {'columns':['BillingAddress', 'DeliveryAddress', 'OrderPositionList'], 'mode':'exclude'})}
	
		<#list ofv['BillingAddress'] as b>
        	${addColumns(row, b, "BillingAddress_")}
		</#list>

		<#list ofv['DeliveryAddress'] as d>
			${addColumns(row, d, "DeliveryAddress_")}
		</#list>

<#--		<#list ofv['OrderPositionList'] as m>
			${addColumns(row, m, "OrderPositionlist_")}
         </#list> -->

        <#list ofv['OrderPositionList']['Items'] as itm>
        <#assign row = target.addRow()> 
          ${addColumns(row, itm, "Items_")} 
        </#list>
          
</#list>

Hier noch die Response. Die Spalten „BuyerCompanyDisplayName“, und „BuyerCompanyId“ stehen stellvertretend für eine Vielzahl an Spalten, u.A. OrderToken - den ich unbedingt in den Artikelzeilen brauche.

Als Parent-/Variant ist das nicht denkbar, da die Spalten beider Tabellen unterschiedlich sind.

Hilffeeeeee :smiley:

LG,
Sebastian

Hallo Sebastian,

ich glaube du musst nur noch die gewünschten Daten aus dem OrderForView Objekt in den itm Zeilen einfügen:

         <#list ofv['OrderPositionList']['Items'] as itm>
            <#assign itemRow = target.addRow()> 

            <#-- einzelne Spalte -->
  	        ${itemRow.addCol("BuyerCompanyId", ofv['BuyerCompanyId'])}
        
             <#-- alle Spalten -->
             <#-- ${addColumns(itemRow, ofv, "", {'columns':['BillingAddress', 'DeliveryAddress', 'OrderPositionList'], 'mode':'exclude'})} -->

            ${addColumns(itemRow, itm, "Items_")} 
        </#list>

Innerhalb der list Anweisung wird für jedes Item Objekt eine neue Zeile erstellt:
<#assign itemRow = target.addRow()> (ich habe die Variable mal in itemRow umbenannt, damit es deutlicher wird das es eine neue Zeile im Ergebnis ist)

In den (item) Zeilen kannst du jetzt auch Daten aus übergeordneten Objekten hinzufügen. Für eine einzelne Spalte kannst du z.B.
${itemRow.addCol("BuyerCompanyId", ofv['BuyerCompanyId'])}
verwenden. Das Ergebnis sollte dann in etwa so aussehen:

Wenn du alle Spalten brauchst, kannst du auch die addColumns Funktion verwenden (wie in der Kopfzeile)
${addColumns(itemRow, ofv, "", {'columns':['BillingAddress', 'DeliveryAddress', 'OrderPositionList'], 'mode':'exclude'})}

Das Ergebnis enthält dann alle Kopfdaten in den Positionszeilen:


Ich hoffe das hilft dir etwas weiter. Falls du noch Fragen hast kannst du dich gerne nochmal melden.

Viele Grüße
Torsten

1 Like

Hi Thorsten,
danke für deinen Post!

Das ist genau, wonach ich gesucht hatte. Ich konnte mir einfach nicht vorstellen, dass es so eine Funktion nicht gibt.

Für meine Mappingfrage mache ich mal einen neuen Thread auf. Parsing ist jetzt im Groben erstmal verstanden.

Danke @synesty-Lukas, @synesty-Torsten und @synesty-Sales für die klasse Hilfe!