วิธีการแยกรายการด้วยแผนที่ไปยัง Wrapperclass

Aug 18 2020

ฉันมีสตริงที่ฉันพยายามที่จะ deserialize เป็น wrapperclass / object แต่ได้รับข้อผิดพลาด:

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;
}

สตริง

[
  {
    "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"
  }
]

เอเพ็กซ์

 system.debug((List<Invocable_Obj_HandleInvoice>) System.JSON.deserialize(invoices, List<Invocable_Obj_HandleInvoice>.class));  

รายชื่อส่งไปยังส่วนประกอบฟ้าผ่า

 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;

ตัวควบคุมสายฟ้า

var act = cmp.get("c.updateInvoices");
var updatedInvoiceList = JSON.stringify(cmp.get('v.handleInvoices'));
act.setParams({ "invoices" : updatedInvoiceList});
$A.enqueueAction(act); 

ส่วนประกอบ <ออร่า: แอตทริบิวต์ type = "รายการ" name = "handleInvoices" />

ตัวควบคุมสายฟ้า

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"

อัปเดต ***** สำหรับใครก็ตามที่ประสบปัญหานี้ฉันพบคำตอบด้านล่างนี้เพื่อแก้ไขปัญหาของแผนที่ แต่หลังจากที่ระบุว่าแผนที่ยังคงมีการเปลี่ยนแปลงดังนั้นฉันจึงยุติการรวมโซลูชันนี้โดยส่งผ่านวัตถุโดยตรง: วิธีส่งวัตถุจาก ตัวช่วย Lightning Component สำหรับวิธี 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); 

คำตอบ

3 sfdcfox Aug 18 2020 at 19:40
@AuraEnabled global Map<String, String> availableOptions;

ควรจะเป็น:

@AuraEnabled global List<Map<String,String>> availableOptions;

หรือ:

@AuraEnabled global List<KeyValuePair> availableOptions;

อยู่ที่ไหนKeyValuePair:

public class KeyValuePair {
  @AuraEnabled public String key;
  @AuraEnabled public String value;
}

ซึ่งใช้กันทั่วไปมากพอในโค้ดที่ฉันมีเป็นคลาสระดับบนสุดในองค์กรผู้พัฒนาของฉัน ฉันใช้มันค่อนข้างบ่อยสำหรับค่ารายการเลือกและอื่น ๆ

โดยทั่วไปแล้ว JSON ประเภทนี้ไม่ได้รับการสนับสนุน แต่ถ้าคุณต้องใช้ในลักษณะนั้นนี่คือรูปแบบที่ต้องการ ในการใช้เอเพ็กซ์ดั้งเดิมของคุณจำเป็นต้องจัดรูปแบบเป็น:

"availableOptions": { "e": "f", "g", "z" },

ซึ่งเป็นวิธีการจัดรูปแบบ JSON ในความหมายทั่วไปแม้ว่ารูปแบบก่อนหน้านี้จะยอมรับได้สำหรับกรณีต่างๆเช่นตัวเลือกรายการเลือกซึ่งมีค่าและป้ายกำกับ


ดูเหมือนว่าคุณต้องเปลี่ยน "availableOptions" ของคุณกลับไปเป็นแผนที่ที่เหมาะสมเพื่อให้ใช้งานได้อย่างถูกต้อง:

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); 
DerekF Aug 18 2020 at 19:41

availableOptions ใน JSON ของคุณไม่ใช่แผนที่ แต่เป็นรายการวัตถุ (ที่มีช่อง "คีย์" และ "ค่า")

ดังนั้นคลาส Wrapper ของคุณจึงต้องสะท้อนสิ่งนั้น แทนที่จะเป็นMap<String, String>คุณต้องทำให้เป็น List ของคลาส / ประเภทอื่นที่สามารถเก็บข้อมูลเป้าหมายได้ ("คีย์" และ "ค่า")