The Apex development team changed the behavior of the JSON serialization in response to several customer issues.
As you are aware, we will typically version changes to the system behavior where possible, in order to protect backward compatibility. There are situations in which we do not version behavior, however. We made an assumption that JSON parsers would not have an issue not receiving null values, since the information received is not relevant. It's like the junk mail you reflexively throw out when sifting through your mail.
As per your post, it's clear that some parsing strategies depend on null values being included in the JSON output. We apologize that our assumption was incorrect, and that your integration and others were unable to operate with the new version.
We have undone the change for the Spring '13 release. To support the original customer cases that prompted these changes, we will version in the originally intended fix in the Summer release.
Thanks,
Josh Kaplan
Product Manager, Apex Code
Rational for Error: JSON does not encoded the data types of the data, thus you have to give your class type to allow it to understand how to parse the data as it works its way through the class members. The Object data type is not enough for the deserialize method to know the data type.
Using JSON.deserializeUntyped. To work around this you can manually parse the JSON using the various JSON parser methods or use the deserializeUntyped method which returns conveniently a map that contains primitive data types!
So I've leveraged this in some new methods to encapsulate this with your Parameters class.
public class Parameters{
private Map<String, Object> parameters = new Map<String, Object>();
public void add(String name, Object value) {
this.parameters.put(name, value);
}
public Object get(String name) {
Object result = null;
if(this.parameters.containsKey(name)) {
result = this.parameters.get(name);
}
return result;
}
public String serialize()
{
return JSON.serialize(parameters);
}
public static Parameters deserialize(String serialized)
{
Parameters parameters = new Parameters();
parameters.parameters = (Map<String, Object>) JSON.deserializeUntyped(serialized);
return parameters;
}
}
This is a slightly modified version of your test code to use the new helper methods.
Parameters params = new Parameters();
params.add('Name', 'Robert');
params.add('Age', 36);
String serialized = params.serialize();
Parameters deserialized = Parameters.deserialize(serialized);
System.assertEquals(params.toString(), deserialized.toString());
I've used toString to compare equality, as without it the check fails, as the two variables point to different instances of the same object.
Alternative:
This naked version also works as well...
Map<String, Object> parameters = new Map<String, Object>();
parameters.put('A', 36);
parameters.put('B', 'Robots');
String serialized = JSON.serialize(parameters);
System.debug(serialized);
parameters = (Map<String, Object>) JSON.deserializeUntyped(serialized);
System.debug(parameters.get('B'));
Best Answer
Use the alternative method signature:
Using your code as an example: