How to Handle Reserved Words in JSON Deserialization?

Spread the love

Question

How to Deserialize JSON into an Object in Apex When Property Names Are Reserved Words?

Is there a way to deserialize JSON into an Apex object using JSON.deserialize if some property names in the JSON are reserved keywords in Apex? For example, I want to deserialize the following JSON:

{
    "currency": "ABC"
}

Here’s my Apex class and code:

string jsonString = '{"currency" : "ABC"}';
public class JSONResult {
    public string currency;
}
JSONResult res = (JSONResult) JSON.deserialize(jsonString, JSONResult.class);
system.debug(res);

However, this throws an error because currency is a reserved keyword in Apex. How can I handle this scenario and successfully deserialize the JSON? Any help or workarounds would be appreciated!

Answer

In Apex, certain words are reserved and cannot be used as identifiers, such as variable or property names. This creates a challenge when trying to deserialize JSON that contains these reserved words as property names. For instance:

String jsonString = '{"currency" : "ABC"}';

public class JSONResult {
    public String currency;
}

// Attempting to deserialize
JSONResult res = (JSONResult) JSON.deserialize(jsonString, JSONResult.class);
System.debug(res);

The above code results in an error because currency is a reserved word in Apex. There are two common ways to address this issue, along with an advanced solution using a custom serializer/deserializer:

1. String Replacement in the JSON String

One straightforward solution is to replace the reserved word in the JSON string with a non-reserved substitute before deserialization. After processing, you can replace it back if necessary. For example:

String jsonString = '{"currency" : "ABC"}';
jsonString = jsonString.replace('"currency":', '"currency_x":');

public class JSONResult {
    public String currency_x;
}

JSONResult res = (JSONResult) JSON.deserialize(jsonString, JSONResult.class);
System.debug(res.currency_x); // Outputs: ABC

In this code, the reserved keyword currency is replaced with currency_x in the JSON string, and the JSONResult class defines a matching property. This allows successful deserialization, avoiding reserved word conflicts. The debug statement prints the deserialized value of the currency_x property.

2. Manually Parsing JSON with JSONParser

Another approach is to use the JSONParser class to manually parse the JSON string and map reserved words to acceptable identifiers. While this method is accurate and flexible, it requires more effort and can be tedious if the JSON structure changes frequently.

String jsonString = '{"currency" : "ABC"}';
JSONParser parser = JSON.createParser(jsonString);

String currencyValue;
while (parser.nextToken() != null) {
    if (parser.getCurrentToken() == JSONToken.FIELD_NAME && parser.getText() == 'currency') {
        parser.nextToken();
        currencyValue = parser.getText();
    }
}
System.debug(currencyValue); // Outputs: ABC

Here, the JSONParser is used to process the JSON string token by token. When the parser encounters the currency field, it retrieves the associated value. This avoids deserialization errors related to reserved words while maintaining full control over the parsing logic.

3. Using a Custom Serializer/Deserializer

For a more robust solution, you can implement a custom serialization and deserialization framework that maps reserved keywords to alternative names during processing. Here’s an example based on the implementation by Charlie Jonas:

Custom Abstract Class:

public abstract class JSONReservedSerializer {
    private final Map<Type, Map<String, String>> typeMapKeys;

    public JSONReservedSerializer(Map<Type, Map<String, String>> typeMapKeys) {
        this.typeMapKeys = typeMapKeys;
    }

    public String serialize(Object obj, System.Type type) {
        String retString = JSON.serialize(obj);
        return transformForSerialization(retString, typeMapKeys.get(type));
    }

    public Object deserialize(String jsonString, System.Type type) {
        jsonString = transformForDeserialization(jsonString, typeMapKeys.get(type));
        return JSON.deserialize(jsonString, type);
    }

    private static String transformForSerialization(String s, Map<String, String> mapKeys) {
        for (String key : mapKeys.keySet()) {
            s = s.replaceAll('"' + key + '"(\\s*):', '"' + mapKeys.get(key) + '":');
        }
        return s;
    }

    private static String transformForDeserialization(String s, Map<String, String> mapKeys) {
        Map<String, String> reversedMap = new Map<String, String>();
        for (String key : mapKeys.keySet()) {
            reversedMap.put(mapKeys.get(key), key);
        }
        return transformForSerialization(s, reversedMap);
    }
}

In this abstract class, mappings between reserved keywords and alternative names are maintained in a map. The transformForSerialization and transformForDeserialization methods handle bidirectional replacements, ensuring reserved words are appropriately substituted during serialization and deserialization.

Implementation:

public class MySerializer extends JSONReservedSerializer {
    private static final Map<String, String> MAPPINGS = new Map<String, String> {
        'currency' => 'currency_alias'
    };

    public MySerializer() {
        super(new Map<Type, Map<String, String>> {
            JSONResult.class => MAPPINGS
        });
    }

    public class JSONResult {
        public String currency_alias;
    }
}

String jsonString = '{"currency" : "ABC"}';
MySerializer serializer = new MySerializer();
MySerializer.JSONResult res = (MySerializer.JSONResult) serializer.deserialize(jsonString, MySerializer.JSONResult.class);
System.debug(res.currency_alias); // Outputs: ABC

This implementation defines a custom serializer and a mapping for reserved words. The JSONReservedSerializer class substitutes currency with currency_alias during deserialization. The mapped property is then accessed without any errors, making it suitable for handling APIs or JSON with reserved keywords.

Summing Up

To handle reserved words in JSON deserialization in Apex, you have three main options:

  1. String Replacement: Replace reserved words in the JSON string with acceptable alternatives before deserialization. This is simple but risky if unintended replacements occur.
  2. Manual Parsing with JSONParser: Use Apex’s JSONParser to manually extract and process data, ensuring full control over reserved word handling but requiring more effort for complex structures.
  3. Custom Serializer/Deserializer: Implement a custom serialization framework to map reserved keywords to alternative identifiers. This robust solution works well for APIs with consistent structures but involves an initial setup effort.

Each approach has trade-offs, and the best choice depends on the complexity of your JSON and your use case.

Enroll for Career-Building Salesforce Training with Real-Time Projects

Our Salesforce training in India delivers an all-encompassing learning experience, crafted to help you gain mastery over the Salesforce platform and pave the way for a successful career. Whether you aspire to become a Salesforce Administrator, Developer, or work on AI integrations, our courses delve into every essential aspect of the platform. With an emphasis on practical application through real-world projects, our training ensures you build hands-on expertise and can address real business challenges effectively. Guided by experienced industry professionals, our program equips you with the knowledge and confidence to thrive in the Salesforce ecosystem.

In addition to comprehensive technical training, our Salesforce training in India provides exceptional career development support. This includes personalized mentorship and expert advice to help you prepare for certifications. From in-depth learning materials to real-time project work and targeted interview coaching, we ensure you’re fully prepared for the job market. Our ultimate goal is to not only strengthen your Salesforce proficiency but also to position you for success in your next role. By completing the program, you’ll acquire the skills, experience, and confidence needed to excel in Salesforce and advance your career.


0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x
Open Chat
1
Dear Sir/Madam
How can I help you?