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
SalesRedSalesRed 

JSON Deserialize: "Invalid conversion from runtime type String to Integer"

Hi,

 

I have an unusual occurence occuring and I thought I'd check if anyone may know why it happens.

- I have a class instance reference which I serialise to JSON using the Apex JSON serialize function http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_json.htm

 

I then pass this Sting as an argument to a function and when I try to deserialize it to create a new class instance I get an error as follows  "Invalid conversion from runtime type String to Integer"

 

I'm a bit confused as to why, when I serialize my object to JSON using the APEX function but then try to deserialize it at a later stage that it then fails (when it's again via APEX)

 

Has anyone come across this before?  Is it a bug or is there a solution for this?

 

Thanking you in advance for any help. 

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

JSON requires that all keys be strings. In honor of this restriction, map keys will always be converted to strings. This limitation is required to maintain compliance with other systems that use JSON. You should not attempt to manually manipulate the keys so that they are proper integers, nor should you attempt to generate a JSON string where the keys are integers (or any non-String types). As stated before, you can convert integers to strings before serialization and back after deserialization. Integer.valueOf can convert strings back to numbers. Out of curiousity, why would you necessarily need an Intger key as opposed to just making an array?

 

Edit:

 

See http://www.json.org/ and http://www.jsonlint.com/.

All Answers

sfdcfoxsfdcfox
Could you post the class definitions or data types you are serializing and deserializing? If it's a custom object, are you serializing/deserializing into the same object? I'm not aware of any situation where it would fail if the data types are same for both serializing and deserializing...
SalesRedSalesRed

Hi sfdcfox,

 

My class does not represent a standard or custom object on the platform but is an Apex class/object representation.


I create an instance of my Apex class, then after some processing I serialize the instance to JSON, then at a later stage need to deserialize this JSON string back to a class instance.

 

The following is an example of the process I've been just doing to test out serializing and deserializing my class using JSON

- I Instantiate my class

 

MyClass myClassInstance = new MyClass();

 

- I then perform actions with my classInstance (calling functions, setting variables etc...)

- I then create a serialized string of my class instance

 

String mySerializedJSONString = JSON.serialize(myClassInstance);

System.debug('JSON Representation of Instance = ' + mySerializedJSONString);

 

- The above debug works ok and looks like a correctly formatted JSON string

- I then deserialize the JSON to create a class instance again


MyClass myNewClassInstance=(MyClass)JSON.deserialize(mySerializedJSONString, MyClass.class);

 

At this point I get my "Invalid conversion from runtime type String to Integer" error.

 

Am I incorrectly using the deserialize function above?

 

Thanks for your help.

sfdcfoxsfdcfox

Can you post the JSON string?

SalesRedSalesRed

Hi sfdcfox,

 

Thank you for your help.

 

Here is an example of the JSON string. 

 

{"productDetail":[],"selectedHotel":null,"itemIndex":0,"bedroomChoiceParameters":null,"hotelWebsiteURL":null,"processVoucher":null,"panels":{"1":{"bookingItems":{"0":{"typeName":"MULTICHAIN","type":{},"chainSynopsis":null,"readOnly":null,"itemIndex":null,"msg":null,"mandatory":null,"description":null,"isSeasonal":false,"processImmediately":null,"hidden":null,"field":"startBooking","multipleDates":null,"pageLayout":null,"buttonAction":null,"value":"ProcessInstantly"}},"additionalItems":{}}},"externalService":"http://mytest.com","bookingNumber":null}

SalesRedSalesRed

I've come across the following which may be a contributor to the error I am receiving

 

"Deserialized Map objects whose keys are not strings won't match their corresponding Map objects before serialization. Key values are converted into strings during serialization and will, when deserialized, change their type. For example, a Map<Object, sObject> will become a Map<String, sObject>."  (taken from http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_methods_system_json_overview.htm)

 

I do have a map with integer keys within my class.  I guess when this has been deserialized it changed the keys to Strings.

 

is the only solution to manually deserlaize my JSON to overcome this issue  (or change my keys to strings if this can be done easily)?

 

Thanks.

sfdcfoxsfdcfox
I was not specifically aware of this limitation (not that I've had a need to so far), but it appears that this is the case. Use a String or Id type for map keys. Other types of keys are unreliable at best, or downright destructive at worst (as you found out). You can use custom JSON parsing (there's a JSON parser class for custom parsing), but you'll suffer performance penalties. I'd rather just add a String.valueOf() function to each place where you're storing and retrieving the key for the map; it would probably require the least amount of code modification.
SalesRedSalesRed

Thanks for the suggestions sfdcfox.  I was wondering if there was a way of just passing/denoting an integer key within a JSON string.  As double quotes are used it's as if all keys are treated as strings.  If the panels key "1" in my above example could just be set without the double quotes it would probably resolve my issue, but I'm not sure if the JSON string can be created this way.

sfdcfoxsfdcfox

JSON requires that all keys be strings. In honor of this restriction, map keys will always be converted to strings. This limitation is required to maintain compliance with other systems that use JSON. You should not attempt to manually manipulate the keys so that they are proper integers, nor should you attempt to generate a JSON string where the keys are integers (or any non-String types). As stated before, you can convert integers to strings before serialization and back after deserialization. Integer.valueOf can convert strings back to numbers. Out of curiousity, why would you necessarily need an Intger key as opposed to just making an array?

 

Edit:

 

See http://www.json.org/ and http://www.jsonlint.com/.

This was selected as the best answer
SalesRedSalesRed
Thanks sfdcfox for all your advice. I guess integer converting or array's look like my best option.

Thanks again.
AmandaByrnePBOAmandaByrnePBO
I'm currently trying to finish an Apex class that implements Process.PluginResult, makes an HTTP Get request and returns the JSON results. Although the class passes all tests- I get a version of this error when I add the class to the Flow:  "Invalid conversion from runtime type List to Map"

The documentation samples describing the Process.PluginDescribeResult class intitiate the inputs and outputs as lists, but the PluginResult class demonstrates returning the Process.PluginResult outputs as a Map.  I do deserialize the json and then use another Map<String,Object> to get a specific keyset from the Json.  Could this be what's causing the mismatch? 
AmandaByrnePBOAmandaByrnePBO
or maybe I need two separate Classes with the ProcessPluginDescribe method- one to issue the Get Request and one to return the result?