function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
SImmySImmy 

Please help me with this JSON formatting

Whenever I am trying to hit the platform  event bus in the format below then it gets successful but it's not being parsed as this has single quotes inside Message_Details__c.
{
	"Message_Name__c": "Batch Failure",
	"Source__c": "IPE",
	"Destination__c": "Salesforce",
	"Message_Action__c": "Testing",
	"Message_Details1__c":"{[{'ValidationErrorDetails': 'Duplicate Invoice Batch'},{'ValidationErrorDetails1': 'Duplicate Invoice Batch1'}]}"
}


Response : 
{
    "id": "e06xx0000000001AAA",
    "success": true,
    "errors": [
        {
            "statusCode": "OPERATION_ENQUEUED",
            "message": "1b05b592-cbec-42c1-aa3d-737d3980590c",
            "fields": []
        }
    ]



--------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------
But when I am sending the correct JSON as below then it gives me error : 

{

                "Destination__c": "Salesforce",

                 "Source__c": "IPE", 

                "Message_Action__c": "Success",

                "Message_Name__c":"Invoice",

                "Message_Details1__c": [{  "InvoiceNumber": "DRAFT-0000001", "AWSURL": "the AWS S3 bucket url for the PDF generated"}]
}


Response :

[
    {
        "message": "Cannot deserialize instance of textarea from START_ARRAY value [line:9, column:44]",
        "errorCode": "JSON_PARSER_ERROR"
    }
]

 
TechingCrewMattTechingCrewMatt
Hello. I think you should remove the quotes around the array of objects as seen below:
{
	"Message_Name__c": "Batch Failure",
	"Source__c": "IPE",
	"Destination__c": "Salesforce",
	"Message_Action__c": "Testing",
	"Message_Details1__c":{["ValidationErrorDetails": "Duplicate Invoice Batch"},{"ValidationErrorDetails1": "Duplicate Invoice Batch1"}]}
}

 
SImmySImmy
I've tried everything but it's not working, it gives an error of deserialization as the message details is a text area and it's expecting string values only.
TechingCrewMattTechingCrewMatt
I see what you're saying now. So Message_Details1__c is a Text Area field? 

It will only take text so wrapping it in double quotes will work. How about something like this:
{
	"Message_Name__c": "Batch Failure",
	"Source__c": "IPE",
	"Destination__c": "Salesforce",
	"Message_Action__c": "Testing",
	"Message_Details1__c":"{[\"ValidationErrorDetails\": \"Duplicate Invoice Batch\"},{\"ValidationErrorDetails1\": \"Duplicate Invoice Batch1\"}]}"
}
I tested this in Apex using the following snipet:
Map<String, Object> testMap = new Map<String, Object>();

testMap.put('Message_Name__c', 'Batch Failure');
testMap.put('Source__c', 'IPE');
testMap.put('Destination__c', 'Salesforce');
testMap.put('Message_Action__c', 'Testing');
testMap.put('Message_Details1__c', '{[{"ValidationErrorDetails": "Duplicate Invoice Batch"},{"ValidationErrorDetails1": "Duplicate Invoice Batch1"}]}');

System.debug(String.valueOf(testMap.get('Message_Details1__c')));
System.debug(JSON.serialize(testMap));
System.debug(JSON.deserializeUntyped(JSON.serialize(testMap)));

When the untyped Map is serialized, it had the inner quotes escaped.
SImmySImmy
Actually the thing is the JSON is coming from third party to platform event in Salesforce. And we're getting the JSON in this format: Message_Details1__c":"{[{'ValidationErrorDetails': 'Duplicate Invoice Batch'},{'ValidationErrorDetails1': 'Duplicate Invoice Batch1'}]}" }]}" Can you please check if this format can be replaced through double quotes or deserialized. This would be really a great help.
SImmySImmy
It's been sent through postman and postman doesn't accept the format of message details which you've sent. It's not allowing them to send.
TechingCrewMattTechingCrewMatt
Yes escaping single quotes worked as well:
 
Map<String, Object> testMap = new Map<String, Object>();

testMap.put('Message_Name__c', 'Batch Failure');
testMap.put('Source__c', 'IPE');
testMap.put('Destination__c', 'Salesforce');
testMap.put('Message_Action__c', 'Testing');
testMap.put('Message_Details1__c', '{[{\'ValidationErrorDetails\': \'Duplicate Invoice Batch\'},{\'ValidationErrorDetails1\': \'Duplicate Invoice Batch1\'}]}');

System.debug(String.valueOf(testMap.get('Message_Details1__c')));
System.debug(JSON.serialize(testMap));
System.debug(JSON.deserializeUntyped(JSON.serialize(testMap)));

 
SImmySImmy
Please try this one. { "Message_Name__c": "Batch Failure", "Source__c": "IPE", "Destination__c": "Salesforce", "Message_Action__c": "Testing", "Message_Details1__c":"{[{'ValidationErrorDetails': 'Duplicate Invoice Batch'},{'ValidationErrorDetails1': 'Duplicate Invoice Batch1'}]}" } Please let me know how I can do this one, without slash.
TechingCrewMattTechingCrewMatt
That format should work without the slashes. What are you calling from Postman? The Streaming API? If you surround the text with double quotes and don't have double quotes in the string, it can be deserialized into a text area. It needs to parsed once it's deserialized if you want to read the array.

Maybe some clarification is needed about what you are trying to do.
SImmySImmy
See this is what they are sending through postman
TechingCrewMattTechingCrewMatt
Is that valid JSON? I think it should like the following:
{
                "Destination__c": "Salesforce",
                 "Source__c": "IPE", 
                "Message_Action__c": "Success",
                "Message_Name__c":"Invoice",
                "Message_Details1__c": "[{  'InvoiceNumber': 'DRAFT-0000001', 'AWSURL': 'the AWS S3 bucket url for the PDF generated'}]"
}

 
SImmySImmy
See I am getting success response. User-added image
SImmySImmy
Now my question is what should I do to make this format : "Message_Details1__c" : "{[{'ValidationErrorDetails': 'Duplicate Invoice Batch'},{'ValidationErrorDetails1': 'Duplicate Invoice Batch1'}]}" "

to the one which you suggested : 
'{[{\'ValidationErrorDetails\': \'Duplicate Invoice Batch\'},{\'ValidationErrorDetails1\': \'Duplicate Invoice Batch1\'}]}'
 
Also I am unable to execute this code in developer console :

Map<String, Object> testMap = new Map<String, Object>();

testMap.put('Message_Name__c', 'Batch Failure');
testMap.put('Source__c', 'IPE');
testMap.put('Destination__c', 'Salesforce');
testMap.put('Message_Action__c', 'Testing');
testMap.put('Message_Details1__c', '{[{'ValidationErrorDetails': 'Duplicate Invoice Batch'},{'ValidationErrorDetails1': 'Duplicate Invoice Batch1'}]}');            
System.debug(String.valueOf(testMap.get('Message_Details1__c')));
System.debug(JSON.serialize(testMap));
System.debug(JSON.deserializeUntyped(JSON.serialize(testMap)));

 
SImmySImmy
And the solution which you suggested will also not going to work for them :
Map<String, Object> testMap = new Map<String, Object>();

testMap.put('Message_Name__c', 'Batch Failure');
testMap.put('Source__c', 'IPE');
testMap.put('Destination__c', 'Salesforce');
testMap.put('Message_Action__c', 'Testing');
testMap.put('Message_Details1__c', '{[{\'ValidationErrorDetails\': \'Duplicate Invoice Batch\'},{\'ValidationErrorDetails1\': \'Duplicate Invoice Batch1\'}]}');

System.debug(String.valueOf(testMap.get('Message_Details1__c')));
System.debug(JSON.serialize(testMap));
System.debug(JSON.deserializeUntyped(JSON.serialize(testMap)));

If I paste the Message_details1__c inside postman then it's not a valid json. So it will always be the one which I have show on the previous post. 
'{[{\'ValidationErrorDetails\': \'Duplicate Invoice Batch\'},{\'ValidationErrorDetails1\': \'Duplicate Invoice Batch1\'}]}'

User-added image
TechingCrewMattTechingCrewMatt
In Postman, they shouldn't need to escape the single quotes. The following should be good:
"[{'ValidationErrorDetails': 'Duplicate Invoice Batch'},{'ValidationErrorDetails1': 'Duplicate Invoice Batch1'}]"
The concern is wht you need to do with the payload after the event is published. It will need to be deserialized to get the Message_Details1__c, and then that string will need to be deserialized to get the array of objects.
 
SImmySImmy
Thank you for the clarification. But how should I write the code for that. Could you please help me with that?
TechingCrewMattTechingCrewMatt
It's uclear to me what you're trying to accomplish. Are you trying to publish an event from an external system and listen for it in Salesforce? Where is the data in Message_Details1__c going to be used? On another record, a Visualforce page, a Lightning component, etc?
SImmySImmy
Yes you are right. I'm trying to publish the event from an external source. And this data will be stored in custom object which I've created just for the tracking purpose. And then this will be updating a record on the basis of certain criteria/ field's values. Hope it would be clear to you. Please let me know if you have any questions.
TechingCrewMattTechingCrewMatt
A sample platform event trigger is below. You can alter this to implement the logic you are describing. Please mark this question as answered.
trigger PlatformEventTrigger on Event__e (after insert) {
    List<SObject> recordsToInsert = new List<SObject>();
    for(Event__e insertedEvent : Trigger.new){
    	List<Object> messageDetails = (List<Object>)JSON.deserialize(insertedEvent.Message_Details1__c);
        SObject recordToInsert = new SObject();
        for(Object detail : messageDetails){
            Map<String, Object> detailMap = (Map<String, Object>)JSON.deserializeUntyped(detail);
            String fieldValue;
            if(detailMap.containsKey('InvoiceNumber')){
                fieldValue = String.valueOf(detailMap.get('InvoiceNumber'));
            }
            else{
                fieldValue = String.valueOf(detailMap.get('ValidationErrorDetails'));
            }
            SObject.put('Name', fieldValue);
        }
        recordsToInsert.add(recordToInsert);
    }
    insert recordsToInsert;
}