0

I want to be able to Generically deserialize a Json string with nested arrays for a web-service, since the structure isn't known beforehand and kan change a lot. I did some reading a seems doable but not more than 4 levels deep.

Please point me in the right direction with an example since this seems to be possible for 1 level, how to do this with nested arrays given not more than 4 levels deep.

My current approach would be:

  1. An interface to talk to from outside
  2. Generically deserialize Json
  3. Custom metadata to map field to sObject

Thanks in advance.

2

The API to deserialize JSON of indeterminate structure is:

JSON.deserializeUntyped

described in the JSON Class documentation. I have used this often and have not hit any depth problems; add a link to any evidence of that.

That will return arrays and maps of Object and so your code will need to cast appropriately. This can be static - the code assumes and casts - or dynamic - the code uses instanceof (and other type detection) and bases the casting on that. Putting the mapping to SObject fields in some kind of configuration or at the very least in some static Apex maps makes sense. Note that you will probably have to implement type conversion for e.g. dates

(Perhaps not relevant here, but in general, do consider json2apex that has the benefit of generating data holding classes for you. If your JSON only has a small number of permutations you could generate per permutation and select the appropriate one via a preliminary JSON.deserializeUntyped.)

My goto reference for what can turn up in JSON is this single Introducing JSON page.

2
  • Whilst it is fairly cool, I'm not a fan of json2apex as it doesn't generate clean, standalone POTATOs in which to represent the JSON data, doesn't cope well with repeated fragments of JSON in slightly different cases and requires an exhaustive example of possible JSON structuring to work. This is OK for small and simple JSON payloads, but not much use for anything more complex (IMHO). It also doesn't prevent property repetition and for anything but type/property validation either requires the validation to be separated from the POTATOs or the generated code to be modified. – Phil W Jan 8 at 8:35
  • Hi @PhilW, I agree about json2apex and have only used it occasionally. Just think it is important for people to know what the options so they can make a good choice. I cringe when I see flakey, hand written JSONGenerator code when json2apex could have generated the correct code. – Keith C Jan 8 at 10:14
0

To Deserialize JSON you can use:

JSON.deserializeUntyped

To parse JSON for multiple levels using JSON.deserializeUntyped you need another layer of typecasting.

Here is an example:

JSON To Parse:

{
   "Candidates":[
      {
         "Name":"ABC",
         "Exp":25,
         "Languages":[
            {
               "Name":"Apex",
               "version":[
                  
               ]
            },
            {
               "Name":"Java",
               "versions":[
                  {
                     "version":1.8,
                     "certification":true,
                     "placeholder":
                        {
                           "target":"reached"
                        }
                  }
               ]
            }
         ]
      },
      {
         "Name":"DEF",
         "Exp":26
      }
   ]
}

Let's say we need to reach the target attribute. Levels are Candidates>Languages>versions>placeholder>target.

You can achieve it by additional type casting for each level you move. Here is the solution:

String jsonInput = '{'+
   '"Candidates":['+
      '{'+
         '"Name":"ABC",'+
         '"Exp":25,'+
         '"Languages":['+
            '{'+
               '"Name":"Apex",'+
               '"versions":['+
                  
               ']'+
            '},'+
            '{' +
               '"Name":"java",'+
               '"versions":['+
                  '{'+
                     '"version":1.8,'+
                     '"certification":true,'+
                     '"placeholder":'+
                        '{'+
                           '"target":"reached"'+
                        '}'+
                     ''+
                  '}'+
               ']'+
            '}'+
         ']'+
      '},'+
      '{'+
         '"Name":"DEF",'+
         '"Exp":26'+
      '}'+
   ']'+
'}';

//Deserialize the specified JSON string into collections of primitive data types.
Map<String, Object> m = 
   (Map<String, Object>)
      JSON.deserializeUntyped(jsonInput);
//level-1     
List<Object> Candidates = (List<Object>)m.get('Candidates');

for(Object Candidate : Candidates){
    String Name = (String)((Map<String, Object>) Candidate).get('Name');
    if(Name == 'ABC'){
        //level-2
        List<Object> Languages = (List<Object>)((Map<String, Object>) Candidate).get('Languages');
        for(Object Language : Languages){
            String LanguageName = (String)((Map<String, Object>) Language).get('Name');
            if(LanguageName == 'java'){
                //level-3
                List<Object> versions = (List<Object>)((Map<String, Object>) Language).get('versions');
                for(Object version : versions){
                    Decimal versionNo = (Decimal)((Map<String, Object>) version).get('version');
                    if(versionNo == 1.8){
                        //level-4
                        Map<String, Object> placeholder = (Map<String, Object>)((Map<String, Object>) version).get('placeholder');
                        //level-5
                        String target = (String)placeholder.get('target');
                        System.debug(target);
                    }
                }
            }
        }
    }
}
2
  • Is there a way to dynamically deserialize the Json in collective datatypes is the structure is not known beforcehand? – Thomas Jan 21 at 1:21
  • @Thomas, Can you explain a bit more how exactly you want to achieve it? I have done it using the same method. Can you tell me more about your scenario? – Umang Barot Feb 6 at 9:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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