0

To summarize very quickly I am building a REST Integration between two Salesforce environments, where I am querying data from the Source and sending them via Callout to my Target, which has a WebService with a Put method to receive them.

Authentication, sending and receiving is working correctly when I send one record at a time, but my json format is wrong when sending a list.

I want to change my json format on the receiving end from:

[{"attributes":{"type":"Apttus_Config2__PriceList__c","url":"/services/data/v45.0/sobjects/Apttus_Config2__PriceList__c/aGA0E000000003mWAA"},"APTS_Ext_ID__c":"aGA0E000000003mWAA","Name":"TEST - Update1","Id":"aGA0E000000003mWAA"},{"attributes":{"type":"Apttus_Config2__PriceList__c","url":"/services/data/v45.0/sobjects/Apttus_Config2__PriceList__c/aGA0E0000000046WAA"},"APTS_Ext_ID__c":"aGA0E0000000046WAA","Name":"TEST2 - update1","Id":"aGA0E0000000046WAA"}]

to:

{"Apttus_Config2__PriceList__c": [{"APTS_Ext_ID__c":"aGA0E000000003mWAA","Name":"TEST - Update1","Id":"aGA0E000000003mWAA"},{"APTS_Ext_ID__c":"aGA0E0000000046WAA","Name":"TEST2 - update1","Id":"aGA0E0000000046WAA"}]}

Please note I am not using wrapper classes and I don't intend to - I would rather use some String manipulation, but I am not sure how to do that.

closed as off-topic by glls, Pranay Jaiswal, Jayant Das, Reshma, battery.cord Mar 5 at 14:25

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions on problems in code you've written must describe the specific problem and include valid code to reproduce it. For help writing short, self-contained syntactically-valid examples, see: SSCCE.org" – glls, Pranay Jaiswal, Jayant Das, Reshma, battery.cord
If this question can be reworded to fit the rules in the help center, please edit the question.

  • String json = '{'+ ' \"Apttus_Config2__PriceList__c\": [{'+ ' \"APTS_Ext_ID__c\": \"aGA0E000000003mWAA\",'+ ' \"Name\": \"TEST - Update1\",'+ ' \"Id\": \"aGA0E000000003mWAA\",'+ ' \"url\": \"/services/data/v45.0/sobjects/Apttus_Config2__PriceList__c/aGA0E000000003mWAA\"'+ ' },'+ ' {'+ ' \"APTS_Ext_ID__c\": \"aGA0E0000000046WAA\",'+ ' \"Name\": \"TEST2 - update1\",'+ ' \"Id\": \"aGA0E0000000046WAA\",'+ ' \"url\": \"/services/data/v45.0/sobjects/Apttus_Config2__PriceList__c/aGA0E0000000046WAA\"'+ ' }'+ ' ]'+ '}'; – Gourishankar Mar 4 at 12:11
1

I don't think that string manipulation is the thing to use here. Carrying over from your previous question, I do think part of the Composite resource of the REST API is the way to go here.

That said, I think that deserializing to a List<Object> using JSON.deserializeUntyped(), and then doing your manipulation, is going to be the easiest way to accomplish this.

Normally, we'd be sticking the output of JSON.deserializeUntyped() into a Map<String, Object>, but the highest-level object in your JSON is a list, so we need to match that.

Be warned that there is a good deal of explicit type casting involved.

The example I was able to get working is as follows:

// Your given input string
String jsonString = '[{"attributes":{"type":"Apttus_Config2__PriceList__c","url":"/services/data/v45.0/sobjects/Apttus_Config2__PriceList__c/aGA0E000000003mWAA"},"APTS_Ext_ID__c":"aGA0E000000003mWAA","Name":"TEST - Update1","Id":"aGA0E000000003mWAA"},{"attributes":{"type":"Apttus_Config2__PriceList__c","url":"/services/data/v45.0/sobjects/Apttus_Config2__PriceList__c/aGA0E0000000046WAA"},"APTS_Ext_ID__c":"aGA0E0000000046WAA","Name":"TEST2 - update1","Id":"aGA0E0000000046WAA"}]';

// Again, because the top-level structure of your JSON is a list, we need to use a list here
//   as well.
// JSON.deserailizeUntyped() gives us an Object as a result.
// We need to explicitly tell Salesforce what "more specific type" we expect
List<Object> untyped = (List<Object>)JSON.deserializeUntyped(jsonString);

// This is where we'll build our target output
Map<String, List<Object>> secondOne = new Map<String, List<Object>>();

// This line has a bit going on...
// Each JSON object (besides a list) can be represented as a Map<String, Object>
// The key of the map is the name of the name-value pair in the JSON
// The value of the map is another object that we need to eventually (explicitly) type-cast

// untyped[0], when cast to a map, gets you the keys "attributes", "atps_ext_id", "name", "id"
// fetching the value for "attributes" gives you an object, which we again type-cast to
//   be a Map<String, Object>
// This gives you access to the keys "type", and "url"
Map<String, Object> attributes = (Map<String, Object>)((Map<String, Object>)untyped[0]).get('attributes');

// Now we can actually get at the "type" information
// Because it too is an object, we need to type-cast.
String targetType = (String)attributes.get('type');

// Set up our output so that we can use it in the next step
secondOne.put(targetType, new List<Object>());

// The rest of the work can be done in a loop (since we're just doing the same thing
//   every time)
// Leave the list elements as plain objects for now...
for(Object obj :untyped){
    // One more time, convert into a map
    Map<String, Object> deserialized = (Map<String, Object>)obj;

    // The Map class has a remove() method, which does exactly what you'd think it'd do
    deserialized.remove('attributes');

    // Since you only wanted to get rid of the "attributes", and we've accomplished that,
    //   you can just add the modified map straight into the List<Object> stored
    //   for the given value of targetType.
    // Like Java, everything inherits from Object, and Salesforce does the up-cast
    //   implicitly
    secondOne.get(targetType).add(deserialized);
}

// Just some housekeeping to make Salesforce happy...
Object finalTarget = (Object)secondOne;
String finalJSON = JSON.serialize(finalTarget);

System.debug(finalJSON);

You can run this via anonymous apex (through the developer console) to verify that this works for you.

The output I got when running this was (formatted for readability):

07:47:18:007 USER_DEBUG [147]|DEBUG|
{"Apttus_Config2__PriceList__c":[
    {"Id":"aGA0E000000003mWAA","Name":"TEST - Update1","APTS_Ext_ID__c":"aGA0E000000003mWAA"},
    {"Id":"aGA0E0000000046WAA","Name":"TEST2 - update1","APTS_Ext_ID__c":"aGA0E0000000046WAA"}]
}
  • This is brilliant! And looks to be exactly what I was looking for from the beginning. Best Answer! – MR.M. Mar 12 at 13:33

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