0

I'm facing an issue when generating a JSON dynamically.I've created different inner class to represent the JSON:

public class OrderActions {

    public OrderActions(String type, Object addproduct, Object removeProduct) {

        SM003_Order.TriggerDate triggerdateCE = new SM003_Order.TriggerDate('ContractEffective');
        SM003_Order.TriggerDate triggerdateSA = new SM003_Order.TriggerDate('ServiceActivation');
        SM003_Order.TriggerDate triggerdateCA = new SM003_Order.TriggerDate('CustomerAcceptance');

        List<SM003_Order.TriggerDate> triggerDates = new List<SM003_Order.TriggerDate> ();
        triggerDates.add(triggerdateCA);
        triggerDates.add(triggerdateCE);
        triggerDates.add(triggerdateSA);

        this.triggerDates = triggerDates;
        this.type = type;

        //it's either add or remove, can't be both
        if (addproduct != null) {
            this.Action = addproduct;
        }
        if (removeProduct != null) {
            this.Action = removeProduct;
        }
    }

    public List<TriggerDate> triggerDates { get; set; }
    public String type { get; set; }
    public Object Action { get; set; }
}

Depending on if i want to add a product or remove a product the Action Object can be instantiated in two differents types: Add Product:

public class AddProduct {

    public AddProduct() {
    }

    public AddProduct(String productRatePlanId, List<ChargeOverrides> chargeOverrides) {
        this.chargeOverrides = chargeOverrides;
        this.productRatePlanId = productRatePlanId;
    }

    public String productRatePlanId { get; set; }
    public List<ChargeOverrides> chargeOverrides { get; set; }
}

or Remove Product:

public class RemoveProduct {

    public RemoveProduct(String ratePlanId) {
        this.ratePlanId = ratePlanId;
    }

    public String ratePlanId { get; set; }
}

The problem is that when i serialize the the whole object the JSON is generated like this (add product):

"orderActions": [
    {
      "type": "AddProduct",
      "triggerDates": [
        {
          "name": "ContractEffective",
          "triggerDate": "2020-03-27"
        },
        {
          "name": "ServiceActivation",
          "triggerDate": "2020-03-27"
        },
        {
          "name": "CustomerAcceptance",
          "triggerDate": "2020-03-27"
        }
      ],
      "Action": {
        "productRatePlanId": "8adc9dee710b7521017116c56aa95670",
        "chargeOverrides": [
          {
            "productRatePlanChargeId": "8adc8f99710b7523017116c5cae87a13",
            "pricing": {
              "recurringFlatFee": {
                "listPrice": 17
              }
            }
          }
        ]
      }
    }
  ]

or like this (Remove product):

"orderActions": [
    {
      "type": "RemoveProduct",
      "triggerDates": [
        {
          "name": "ContractEffective",
          "triggerDate": "2020-03-25"
        },
        {
          "name": "ServiceActivation",
          "triggerDate": "2020-03-25"
        },
        {
          "name": "CustomerAcceptance",
          "triggerDate": "2020-03-25"
        }
      ],
      "Action": {
        "ratePlanId": "8adce4216b9de86d016bb3c15fbb0a2f"
      }
    }
  ]

Which is fine except for The key "action" that has to be named either 'addProduct' or 'removeProduct' to respect a specific format. But because of my generic constructor it doesn't generate the good value for this key... Do you guys know how could i change the value of this key?

Cheers!

  • Options 1. You can either write the JSON explicitly, 2. Create two variables named addProduct and removeProduct and set them based the if condition, 3. instead of Action, name the variable as something unique like ACTION_REPLACEMENT and after deserializing replace ACTION_REPLACEMENT with addProduct or removeProduct – manjit5190 Mar 27 '20 at 16:33
  • Thank you for the reply manjit5190. I'd like to avoid to write explicitly le JSON because, it's a complex one (it's only a part of the whole JSON). What do you mean by create two variables? in the class OrderActions ? if so the serialization would generate two different key, addProduct and removeProduct which is incorrect. for the last option i'm not sure to understand... – Fabien Braconnier Mar 27 '20 at 16:43
  • For the second option, you set the other one as null. The serilize method takes an additional parameter to suppress nulls, that way you'll only have either add or remove product in JSON. – manjit5190 Mar 27 '20 at 17:27
  • In addition to Manjit's answer you can just add variables with the "get" property which will either return an action value based on the "instanceof" condition. That is a very small change to your existing code which should satisfy requirements. For example var addProducr returns value of action if value of action is an instance of AddProduct class, returns nukl otherwise – nchursin Mar 28 '20 at 10:50
  • Thank you @manjit5190 the second option worked perfectly! – Fabien Braconnier Mar 31 '20 at 10:01
1

It's not clear from the code how you are generating the JSON dynamically. Here is a sample code that might help.

OrderAction

public class OrderAction {
    public String type;        
    public Action Action;
    public List<TriggerDate> triggerDates = new List<TriggerDate>();

    // CONSTRUCTOR

    public OrderAction(String type) {
        this.type = type;
    }


    public OrderAction add(TriggerDate triggerDate) {
        this.triggerDates.add(triggerDate);

        return this;
    }


    public OrderAction setAction(Action action) {
        this.Action = action;

        return this;
    }


    public class Action {
        public String productRatePlanId;
        public String ratePlanId;

        public List<ChargeOverride> chargeOverrides = new List<ChargeOverride>();

        public Action add(ChargeOverride chargeOverride) {
            this.chargeOverrides.add(chargeOverride);

            return this;
        }


        public Action setProductRatePlanId(String productRatePlanId) {
            this.productRatePlanId = productRatePlanId;

            return this;
        }


        public Action setRatePlanId(String ratePlanId) {
            this.ratePlanId = ratePlanId;

            return this;
        }
    }


    public class TriggerDate {
        public String name;
        public String triggerDate;

        public TriggerDate(String name, String triggerDate) {
            this.name = name;
            this.triggerDate = triggerDate;
        }
    }


    public class ChargeOverride {
        public String productRatePlanChargeId;
        public Pricing pricing;

        public ChargeOverride(String productRatePlanChargeId) {
            this.productRatePlanChargeId = productRatePlanChargeId;
        }


        public ChargeOverride setPricing(Pricing pricing) {
            this.pricing = pricing;

            return this;
        }
    }


    public class Pricing {
        public RecurringFlatFee recurringFlatFee;

        public Pricing(RecurringFlatFee recurringFlatFee) {
            this.recurringFlatFee = recurringFlatFee;
        }            
    }


    public class RecurringFlatFee {
        public Decimal listPrice;

        public RecurringFlatFee(Decimal listPrice) {
            this.listPrice = listPrice;
        }
    }
}

GenericConstructor

public class GenericConstructor {
    public OrderAction getAddProduct() {
        return new OrderAction('AddProduct')
            .add( new OrderAction.TriggerDate('ContractEffective', '2020-03-27'))
            .add( new OrderAction.TriggerDate('ServiceActivation', '2020-03-27'))
            .add( new OrderAction.TriggerDate('CustomerAcceptance', '2020-03-27'))
            .setAction( new OrderAction.Action()
                            .setProductRatePlanId('8adc9dee710b7521017116c56aa95670')
                            .add( new OrderAction.ChargeOverride('8adc8f99710b7523017116c5cae87a13')
                                     .setPricing( new OrderAction.Pricing( new OrderAction.RecurringFlatFee(17)))));
    }


    public OrderAction getRemoveProduct() {
        return new OrderAction('RemoveProduct')
            .add( new OrderAction.TriggerDate('ContractEffective', '2020-03-27'))
            .add( new OrderAction.TriggerDate('ServiceActivation', '2020-03-27'))
            .add( new OrderAction.TriggerDate('CustomerAcceptance', '2020-03-27'))
            .setAction( new OrderAction.Action()
                            .setRatePlanId('8adce4216b9de86d016bb3c15fbb0a2f'));
    }
}
  • Thank you Anmol for the reply. I finally used the method serialize(objectToSerialize, suppressApexObjectNulls) which worked perfectly. – Fabien Braconnier Mar 31 '20 at 10:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.