Come deserializzare un elenco con map in wrapperclass
Ho una stringa che sto cercando di deserializzare in un oggetto / classe di involucro. Ma ottieni l'errore:
Expected Map<String,String> but found [line:1, column:3]
Wrapperclass
global class Invocable_Obj_HandleInvoice {
@AuraEnabled global Id invoiceId;
@AuraEnabled global string invoiceNumber;
@AuraEnabled global decimal balanceAmount;
@AuraEnabled global decimal totalAmount;
@AuraEnabled global string customerName;
@AuraEnabled global string zuoraStatus;
@AuraEnabled global string handlingStatus;
@AuraEnabled global string selectedOption;
@AuraEnabled global Map<String, String> availableOptions;
}
Corda
[
{
"availableOptions": [
{
"key": "e",
"value": "f"
},
{
"key": "g",
"value": "z"
}
],
"balanceAmount": -100,
"customerName": "Test",
"handlingStatus": "New",
"invoiceId": "a0S2o000023CSHoEAO",
"invoiceNumber": "INV-001",
"selectedOption": "A",
"totalAmount": -100,
"zuoraStatus": "Posted"
},
{
"availableOptions": [
{
"key": "a",
"value": "x"
},
{
"key": "b",
"value": "y"
},
{
"key": "c",
"value": "z"
}
],
"balanceAmount": -100,
"customerName": "Test",
"handlingStatus": "New",
"invoiceId": "a0S2o000023CSHoEAO",
"invoiceNumber": "INV-001",
"selectedOption": "y",
"totalAmount": -100,
"zuoraStatus": "Posted"
}
]
Apice
system.debug((List<Invocable_Obj_HandleInvoice>) System.JSON.deserialize(invoices, List<Invocable_Obj_HandleInvoice>.class));
Elenco passato al componente fulmine
List<Invocable_Obj_HandleInvoice> hiList = new List<Invocable_Obj_HandleInvoice>();
Invocable_Obj_HandleInvoice hi1 = new Invocable_Obj_HandleInvoice();
hi1.invoiceId = zi[0].id;
hi1.invoiceNumber = zi[0].Name;
hi1.balanceAmount = zi[0].Zuora__Balance2__c;
hi1.totalAmount = zi[0].Zuora__TotalAmount__c;
hi1.customerName = 'Test';
hi1.zuoraStatus = zi[0].Zuora__Status__c;
hi1.handlingStatus = zi[0].Handling_Status__c;
hi1.selectedOption = 'A';
hi1.availableOptions = new Map<String,string> {'e'=>'f', 'g'=> 'z'};
hiList.add(hi1);
return hiList;
Controller di fulmini
var act = cmp.get("c.updateInvoices");
var updatedInvoiceList = JSON.stringify(cmp.get('v.handleInvoices'));
act.setParams({ "invoices" : updatedInvoiceList});
$A.enqueueAction(act);
Componente <aura: attribute type = "List" name = "handleInvoices" />
Controller di fulmini
doInit : function(cmp, event, helper) {
var action = cmp.get("c.testHandlInvoice");
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
cmp.set('v.handleInvoices', response.getReturnValue());
console.log(cmp.get('v.handleInvoices'));
}
});
$A.enqueueAction(action);
},
console.log
availableOptions: Array(3)
0: {key: "a", value: "x"}
1: {key: "b", value: "y"}
2: {key: "c", value: "z"}
length: 3
__proto__: Array(0)
balanceAmount: -100
customerName: "Test"
handlingStatus: "New"
invoiceId: "a0S2o000023CSHoEAO"
invoiceNumber: "INV-001"
selectedOption: "A"
totalAmount: -100
zuoraStatus: "Posted"
AGGIORNAMENTO ***** Per chiunque si imbattesse in questo problema ho capito che la risposta di seguito affronta il problema della mappa ma dopo aver reso la mappa la mappa è ancora alterata, quindi ho finito di combinare questa soluzione passando direttamente l'oggetto: Come passare un oggetto da un Componente Lightning helper per un metodo Apex Controller
var act = cmp.get("c.updateInvoices");
var tempInvoiceList = cmp.get('v.handleInvoices');
tempInvoiceList = tempInvoiceList.slice(); // copy
tempInvoiceList = tempInvoiceList.map(function(invoice) { return Object.assign({}, invoice); }); // copy deeper
act.setParams({ "invoices" : tempInvoiceList});
tempInvoiceList = tempInvoiceList
.forEach(function(invoice) {
invoice.availableOptions = invoice.availableOptions
.reduce(function(prev, option) {
prev[option.key] = option.value;
return prev;
},
{})
}
);
$A.enqueueAction(act);
Risposte
@AuraEnabled global Map<String, String> availableOptions;
Dovrebbe essere:
@AuraEnabled global List<Map<String,String>> availableOptions;
O:
@AuraEnabled global List<KeyValuePair> availableOptions;
Dov'è KeyValuePair
:
public class KeyValuePair {
@AuraEnabled public String key;
@AuraEnabled public String value;
}
Che è usato abbastanza comunemente nel codice da averlo come classe di primo livello nella mia organizzazione per sviluppatori; Lo uso abbastanza spesso per i valori degli elenchi di selezione e così via.
Questo tipo di JSON è generalmente sconsigliato, ma se devi usarlo in questo modo, questa è la forma preferita. Per poter utilizzare il tuo Apex originale, dovrebbe essere formattato come:
"availableOptions": { "e": "f", "g", "z" },
Questo è il modo in cui JSON deve essere formattato in senso generale, sebbene la forma precedente sia accettabile per casi come le opzioni dell'elenco di selezione, che hanno un valore e un'etichetta.
Sembra che tu debba trasformare le tue "opzioni disponibili" di nuovo in una mappa corretta da utilizzare correttamente:
var act = cmp.get("c.updateInvoices");
var tempInvoiceList = cmp.get('v.handleInvoices');
tempInvoiceList = tempInvoiceList.slice(); // copy
tempInvoiceList = tempInvoiceList.map(function(invoice) { return Object.assign({}, invoice); }); // copy deeper
tempInvoiceList = tempInvoiceList
.forEach(function(invoice) {
invoice.availableOptions = invoice.availableOptions
.reduce(function(prev, option) {
prev[option.key] = option.value;
return prev;
},
{})
}
);
var updatedInvoiceList = JSON.stringify(tempInvoiceLIst);
act.setParams({ "invoices" : updatedInvoiceList});
$A.enqueueAction(act);
availableOptions
nel tuo JSON non è una mappa, è un elenco di oggetti (con i campi "chiave" e "valore").
Quindi la tua classe wrapper deve riflettere questo. Invece di un Map<String, String>
, devi renderlo un elenco di un'altra classe / tipo che può contenere i dati di destinazione ("chiave" e "valore")