[SalesForce] Deserialize JSON Array With Integer Index

I am trying to avoid having to do a JSON deserialized untyped, but not sure if I can…
I get back a response of contact data from a third party that looks something like this:

{"data": {
"1500":{"id":"1500","last_name":"Test1"},
"298":{"id":"298","last_name":"Test2"}
},
"status_code":200}

So if you use JSONtoApex, you get a class like this:

public class jContactsDemo {

    public class Data {
        public 1500 1500;
        public 1500 298;
    }

    public class 1500 {
        public String id;
        public String last_name;
    }

    public Data data;
    public Integer status_code;

Which makes sense – but of course, 1500 and 298 are both contacts with the same structure – so is there some way I am not thinking of to just let me use JSON.deserialize into a Apex Class that can recognize that each entry in the array is the same type?

I had tried to use an initial conversion using JSON.deserializeUntyped, and then loop through results of Map, convert to String, and deserialize each record one at a time:

Map<String, Object> m = (Map<String,Object>)JSON.deserializeUntyped(s);

 for (String s: m.keyset()){
     Map<String, Object> mData = (Map<String, Object>)m.get('data');
     for (String s2: mData.keyset()){
         String sJSON = String.ValueOf(mData.get(s2));
        system.debug(sJSON);
     }   
}

But when I look at the value I get out of the Map, all the double quotes have been removed, which throws a different error…

System.JSONException: Unexpected character ('a' (code 97)): was
expecting double-quote to start field name at [line:1, column:3]

Best Answer

You are going to laugh at this, but it turns out that REENCODING as JSON at each step gets you your quoted values. Strange but true!! Try this:

String jsonData = '{"data": {"1500":{"id":"1500","last_name":"Test1"},"298":{"id":"298","last_name":"Test2"}},"status_code":200}';

//get top level map
Map<String,Object> jsonMap = (Map<String, Object>)JSON.deserializeUntyped(jsonData);

//extract data as JSON
String jsonSubset = JSON.serialize(jsonMap.get('data'));

//re-encode as a Map
Map<String,Object> jsonSubsetMap = (Map<String, Object>)JSON.deserializeUntyped(jsonSubset);

MyContact[] contacts = new MyContact[]{};
for (Object obj : jsonSubsetMap.values()){
    //re-encode as json, again!
    String jsonObj = JSON.serialize(obj);
    //deserialize that b@#$ard!!
    MyContact contact = (EBTestDeleteMe.MyContact)JSON.deserialize(jsonObj, MyContact.class);
    contacts.add(contact);
}

System.debug(contacts);

This outputs:

DEBUG|(MyContact:[id=298, last_name=Test2], MyContact:[id=1500, last_name=Test1])

This assumes you have a class called MyContact that looks like this:

public class MyContact {
    public String id;
    public String last_name;
}
Related Topic