Im running into an de-reference a null object error while trying to serialize a list of objects into JSON for a POST method. The error occurs when it tries to assign a value to line 277 (within the toJSON() function)shipstation_order.shipTo.street1 = cah_order[0].Address_1__c;
. This must be due to me not creating instantiating the sub objects correctly. Any reference or advice would be greatly appreciated!
Here is my current code
public class TotalSales_to_Shipstation_Service implements Queueable,Database.AllowsCallouts{
//************** Shipstation Classes ********************//
public Order[] Shipstation_Orders;
class Order {
public String orderNumber;
public String orderKey;
public String orderDate;
public String paymentDate;
public String shipByDate;
public String orderStatus;
public Integer customerId;
public String customerUsername;
public String customerEmail;
cls_billTo billTo;
cls_shipTo shipTo;
cls_items[] items;
public Double amountPaid;
public Integer taxAmount;
public Integer shippingAmount;
public String customerNotes;
public String internalNotes;
public boolean gift;
public String giftMessage;
public String paymentMethod;
public String requestedShippingService;
public String carrierCode;
public String serviceCode;
public String packageCode;
public String confirmation;
public String shipDate;
cls_weight weight;
cls_dimensions dimensions;
cls_insuranceOptions insuranceOptions;
cls_internationalOptions internationalOptions;
cls_advancedOptions advancedOptions;
public Integer[] tagIds;
}
class cls_billTo {
public String name;
public String company;
public String street1;
public String street2;
public String street3;
public String city;
public String state;
public String postalCode;
public String country;
public String phone;
public boolean residential;
}
class cls_shipTo {
public String name;
public String company;
public String street1;
public String street2;
public String street3;
public String city;
public String state;
public String postalCode;
public String country;
public String phone;
public boolean residential;
}
class cls_items {
public String lineItemKey;
public String sku;
public String name;
public String imageUrl;
cls_weight weight;
public Integer quantity;
public Double unitPrice;
public Double taxAmount;
public Integer shippingAmount;
public String warehouseLocation;
cls_options[] options;
public Integer productId;
public String fulfillmentSku;
public boolean adjustment;
public String upc;
}
class cls_weight {
public Integer value;
public String units;
}
class cls_options {
public String name;
public String value;
}
class cls_dimensions {
public String units;
public Integer length;
public Integer width;
public Integer height;
}
class cls_insuranceOptions {
public String provider;
public boolean insureShipment;
public Integer insuredValue;
}
class cls_internationalOptions {
public String contents;
cls_customsItems customsItems;
}
class cls_customsItems {
public String description;
public Integer quantity;
public Integer value;
public Integer harmonizedTariffCode;
public String countryOfOrigin;
}
class cls_advancedOptions {
public Integer warehouseId;
public boolean nonMachinable;
public boolean saturdayDelivery;
public boolean containsAlcohol;
public boolean mergedOrSplit;
public Integer[] mergedIds;
public Integer parentId;
public String storeId;
public String customField1;
public String customField2;
public String customField3;
public String source;
public String billToParty;
public String billToAccount;
public String billToPostalCode;
public String billToCountryCode;
}
//list of lists to hold grouped ts records with the same order id
List<List<total_sales__c>> cah_orders_formatted = new List<List<total_sales__c>>();
//query is for testing(not final query)
total_sales__c[] ts_list =[
SELECT id,
order_number__c,
createdDate,
Email__c,
First_Name__c,
Last_Name__c,
Address_1__c,
Address_2__c,
City__c,
State_Provence__c,
Postal_Code__c,
Country_Code__c
FROM total_sales__c
WHERE Source__c = 'sourcenamehere'
ORDER BY createdDate DESC
LIMIT 100
];
//************** Methods ********************************//
public void execute(QueueableContext context) {
formatTS();
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint(endpoint);
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json;charset=UTF-8');
String username = key;
String password = secret;
Blob headerValue = Blob.valueOf(username + ':' + password);
String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue);
request.setHeader('Authorization', authorizationHeader);
String jsonBody = toJSON();
request.setBody(jsonBody);
HttpResponse response = http.send(request);
if (response.getStatusCode() != 201) {
System.debug('The status code returned was not expected: ' +
response.getStatusCode() + ' ' + response.getStatus());
} else {
System.debug(response.getBody());
}
}
public void formatTS(){
// create a list to track which order numbers are already in the formated cah list
List<String> ordernumbers = new List<String>();
//loop through each total sale record queried
for(total_sales__c record : ts_list){
//if the order number is not in the tracking list...
if(!ordernumbers.contains(record.order_number__c)){
//add it to the tracking list
ordernumbers.add(record.order_number__c);
//create a new total sales list to hold all of the records with the same order number
List<total_sales__c> cah_order = new List<total_sales__c>();
//add that ts record to the order
cah_order.add(record);
//then add that list to the list that will hold all of the grouped records by order number
cah_orders_formatted.add(cah_order);
// if the order id is found...
}else{
//search the list of lists that contain the grouped records
for(List<total_sales__c> order : cah_orders_formatted){
//once the matching order id is found, add it to that list
if(record.order_number__c == order[0].order_number__c){
order.add(record);
}
}
}
system.debug(cah_orders_formatted);
}
}
public string ifblank(string in_string, string null_value){
string null_txt = '';
if ( null_value != null ){
null_txt = null_value.trim();
}
if (in_string == null ){
return(null_txt);
}
string temp = in_string.trim();
if ( temp.length() < 1 ){
return(null_txt);
}
return(temp);
}
public String toJSON(){
//parse through each list of grouped records
for(List<total_sales__c> cah_order : cah_orders_formatted){
//create a new order object for that list
Order shipstation_order = new Order();
//assign the various values to the shipstation object
shipstation_order.orderNumber = cah_order[0].order_number__c;
//shipstation_order.orderKey(Not Needed)
shipstation_order.orderDate = string.valueOf(cah_order[0].createdDate);
//shipstation_order.paymentDate
//shipstation_order.shipByDate
shipstation_order.orderStatus = 'awaiting_shipment'; //(String- "awaiting_payment", "awaiting_shipment", "shipped", "on_hold", "cancelled")
//shipstation_order.customerId(Read Only)
shipstation_order.customerUsername = cah_order[0].Email__c;
shipstation_order.customerEmail = cah_order[0].Email__c;
//
//shipstation_order.billTo.name(String- First and last)
//shipstation_order.billTo.company(String)
//shipstation_order.billTo.street1(String)
//shipstation_order.billTo.street2
//shipstation_order.billTo.street3
//shipstation_order.billTo.city(String)
//shipstation_order.billTo.state(String)
//shipstation_order.billTo.postalCode(String)
//shipstation_order.billTo.country(String country_code__c)
//shipstation_order.billTo.phone(String)
//shipstation_order.billTo.residential(Boolean)
//
//shipstation_order.shipTo.name = cah_order[0].First_Name__c + cah_order[0].Last_Name__c;
//shipstation_order.shipTo.company
shipstation_order.shipTo.street1 = cah_order[0].Address_1__c;
shipstation_order.shipTo.street2 = cah_order[0].Address_2__c;
//shipstation_order.shipTo.street3
shipstation_order.shipTo.city = cah_order[0].City__c;
shipstation_order.shipTo.state = cah_order[0].State_Provence__c;
shipstation_order.shipTo.postalCode = cah_order[0].Postal_Code__c;
shipstation_order.shipTo.country = cah_order[0].Country_Code__c;
//shipstation_order.shipTo.phone
//shipstation_order.shipTo.residential
//
//shipstation_order.amountPaid(number)
//shipstation_order.taxAmount(number)
//shipstation_order.shippingAmount(number)
//shipstation_order.customerNotes(String)
//shipstation_order.internalNotes(String)
//shipstation_order.gift(Boolean)
//shipstation_order.giftMessage(String)
//shipstation_order.paymentMethod(String)
//shipstation_order.requestedShippingService(???)
//shipstation_order.carrierCode(String)
//shipstation_order.serviceCode(String)
//shipstation_order.packageCode(String)
//shipstation_order.confirmation(String)
//shipstation_order.shipDate(string)
//
//shipstation_order.weight.value(Number)
//shipstation_order.weight.units(String)
//
//shipstation_order.dimensions.units(String)
//shipstation_order.dimensions.lenght(Number)
//shipstation_order.dimensions.width(Number)
//shipstation_order.dimensions.height(Number)
//
//shipstation_order.insuranceOptions.provider(String- "shipsurance", "carrier", or "provider")
//shipstation_order.insuranceOptions.insureShipment(Boolean)
//shipstation_order.insuranceOptions.insuredValue(Number)
//
//shipstation_order.internationalOptions.contents(String- "merchandise", "documents", "gift", "returned_goods", or "sample")
//shipstation_order.internationalOptions.customsItems.description(String)
//shipstation_order.internationalOptions.customsItems.quantity(Number)
//shipstation_order.internationalOptions.customsItems.value(Number in USD)
//shipstation_order.internationalOptions.customsItems.harmonizedTariffCode(String)
//shipstation_order.internationalOptions.customsItems.countryOfOrigin(String Country_code__c)
//
//shipstation_order.advancedOptions.warehouseId
//shipstation_order.advancedOptions.nonMachinable
//shipstation_order.advancedOptions.saturdayDelivery
//shipstation_order.advancedOptions.containsAlcohol
//shipstation_order.advancedOptions.mergedOrSplit
//shipstation_order.advancedOptions.mergedIds
//shipstation_order.advancedOptions.parentId
shipstation_order.advancedOptions.storeId = storeID;
//shipstation_order.advancedOptions.customField1
//shipstation_order.advancedOptions.customField2
//shipstation_order.advancedOptions.customField3
//shipstation_order.advancedOptions.source
//shipstation_order.advancedOptions.billToParty
//shipstation_order.advancedOptions.billToAccount
//shipstation_order.advancedOptions.billToPostalCode
//shipstation_order.advancedOptions.billToCountryCode
//
//shipstation_order.tagIds
//
for(total_sales__c record: cah_order){
cls_items item = new cls_items();
//item.lineItemKey
//item.sku
//item.name
//item.imageUrl
//item.weight.value
//item.weight.units
//item.quantity
//item.unitPrice
//item.taxAmount
//item.shippingAmount
//item.warehouseLocation
//item.options.name
//item.options.value
//item.productId
//item.fulfillmentSku
//item.adjustment
//item.upc
shipstation_order.items.add(item);
}
Shipstation_Orders.add(shipstation_order);
}
String jsonBody = JSON.serialize(Shipstation_Orders);
return jsonBody;
}
}
shipTo
member ofshipstation_order
. Preferably in the contstructor of you inner classOrder
. This probably should be done for all non-standard type variables (billTo
,shipTo
,items
, etc). As a side note, try to prevent using names of existing classes, Apex or SObjects, as names of custom classes.