I want to use the standard Force.com REST API to create a case remotely from another Salesforce instance in my instance. I want to populate two fields on creation: "Subject" and "txt_UserId__c". Because the source org doesn't have the case object, I wrote a custom class that is populated from inputfield values on a visualforce page:

public class CaseMap {
public String Subject {get; set;}
public Id txt_UserId__c {get; set;}
}

Unforunately the property "txt_UserId__c" is not allowed. This means I have to rename it to something else:

public class CaseMap {
public String Subject {get; set;}
public Id UserId {get; set;}
}

But this means, when serializing the class into JSON, one of the field names (i.e., 'UserId'), does not match the API field name that is expected on the target org.

What I did so far is a simple JSON string find and replace operation. But I am sure there must be a more elegant and less fault-prone way to change field names, for example include a mapping table in the serialization or so.

Any ideas?

Thanks!

up vote 7 down vote accepted

You could using the stream JSON api to build your json, or you could build a Map that represents your record, and use regular JSON.serialize to build the json, that's probably easier than the streaming approach, and will be considerably more robust than trying to regex the generated json. e.g.

Map<String, String> r = new Map<String, String>();
r.put('name', 'bob');
r.put('account__c', '0010100000000123');
System.debug(JSON.serialize(r));

generates

09:30:33:071 USER_DEBUG [5]|DEBUG|{"name":"bob","account__c":"0010100000000123"}
  • Very good! This works fine for me, since I have a one-level JSON object! – Nisse Knudsen May 24 '13 at 10:12

I ran into a similar issue not too long ago. There is no annotation you can use to serialize/deserialize reserved keywords in apex. Your options are to either do the string replace or build everything manually using the JSON writer.

I would definitely recommend using a string replace. Something like the following should work for all custom fields:

public class CaseMap {
public String Subject {get; set;}
public Id txt_UserId_c {get; set;}
}

//pass in json body
private String filterRequest(String value) {
    //regex not thoroughly tested
    return value.replaceall('_c"\\s*:', '__c" :');
}
  • Thanks for the approach, although I'll go with superfell's suggestion, I like to use a regex instead of a plain string search! – Nisse Knudsen May 24 '13 at 10:12

In case of suspicious JSON structure, I usually prefer using "JSON.deserializeUntyped". It will safeguard from such issues, and bit safer then string token replacements in JSON.

Pros

Easy and less risky conversion, end result is a simple Map instance, which could be parsed and consumed with ease.

Cons

  • Missing type conversion to CaseMap etc
  • Risk of hitting Heap and Script statement issues: If your JSON is huge, with too many iterations and conversions needed in Apex to create CaseMap type structure (assuming more fields in real code).

More details:

  • 1
    If he is inserting cases via the standard rest api he doesn't have the option of deserializing untyped. The JSON he sends has to match what the api expects. – Greg Grinberg May 23 '13 at 15:52
  • correct, my bad #hurry :) – Abhinav Gupta May 23 '13 at 16:37
  • Not exactly what I've been looking, but I like the Cons, just in general good to know! :) – Nisse Knudsen May 24 '13 at 10:16

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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