I'm strongly considering going the JSON.serialize route suggested here, but before I do, I thought I'd throw this up here. (I prefer JSONGenerator, in theory, because I can specify the field names, which JSON.serialize() isn't as flexible on.)
I'm trying to mimic report output as JSON, replicating an upload of a .csv file, and sketched out two methods; one creates an object for an individual record, the other wraps them into a larger whole.
Here's the inner method, which creates an object representing each row in the exported report - createContactDataFromIVR(): `
String result = '';
JSONGenerator gen = JSON.createGenerator(false);
// basic structure = name(str), contactListId(str), data(Object), callable(boolean), phoneNumberStatus(Object)
// 'data' being the specifics of the particular Contact ^
gen.writeStartObject(); // '['
gen.writeStringField('Patient IVR: Patient IVR Id', ivr.Name);
gen.writeStringField('Phone', ivr.Phone__c);
gen.writeStringField('Patient: First Name', ivr.First_Name__c);
gen.writeStringField('Patient: Last Name', ivr.Last_Name__c);
gen.writeStringField('18 Digit Contact ID', ivr.Patient__c);
gen.writeStringField('18 Digit SFDC ID', ivr.Id);
gen.writeStringField('Patient: Mailing Zip/Postal Code', ivr.Zip_Code__c);
gen.writeEndObject();
result = gen.getAsString();
return result;
I have another method that calls this one, and attempts to add the 'contact' entry into a larger context using JSONGenerator.writeObject(object);
Running the code returns the following error:
System.JSONException: Can not write text value, expecting field name
Looking more closely at JSONGenerator example, I had preceded .writeFieldName(), .writeObject() with .writeStartObject(), which doesn't appear to be needed if you're passing in an object as a whole vs. creating it line-by-line, so I removed .writeStartObject() and went straight from .writeStringField(), the entry immediately preceding the object, to .writeFieldName().
JSONGenerator gen = JSON.createGenerator(false);
// basic structure = name(str), contactListId(str), data(Object), callable(boolean), phoneNumberStatus(Object)
gen.writeStartObject(); // '['
gen.writeStringField('name', ''); // needed(?)
gen.writeStringField('contactListId', listId);
gen.writeFieldName('data');
String contactData = createContactDataFromIVR(ivr);
gen.writeObject(contactData);
gen.writeEndObject();
Which resulted in a new JSONException() (change is good!..?)
System.JSONException: Can not write a field name, expecting a value
Still not great -- I need that 'data' heading as that's what the consuming webservice is expecting. createContactDataFromIVR(ivr) is working fine, but I need to generate more than one, here. This is what createContactDataFromIVR() returns:
{"Patient IVR: Patient IVR Id":"ivr-07/24/18-557675","Phone":"(469) 463-0384","Patient: First Name":"J","Patient: Last Name":"V","18 Digit Contact ID":"0033300001f4XqnAAE","18 Digit SFDC ID":"a19e00000034RxTAAU","Patient: Mailing Zip/Postal Code":"75048"}
The examples that I've found (JSONGenerator Sample) indicate that an Object can be inserted with .writeFieldName('someName'), followed by .writeObject('theObject'). I've used JSONGenerator on 'theObject' already; perhaps that's where it's breaking. I'll try JSON.serialize() on it instead (though as I mentioned at the top^, I'm trying to mimic a .csv exported report, and I can't emulate the field names as precisely using .serialize()..)