1

I'm not sure what to do next with my JSON2Apex generated output since I only need to see the values for three JSON keys. My generated output is approximately 300 lines long and below is a snippet of two types of JSON output that I would receive and parse through.

    {
        "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#groups('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')/drive/root/children",
        "value": [
            {
                "createdDateTime": "2018-06-04T20:30:42Z",
                "eTag": "\"{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx},1\"",
                "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                "lastModifiedDateTime": "2018-06-04T20:30:42Z",
                "name": "Al's Files",
                "webUrl": "https://example.sharepoint.com/sites/it/Shared%20Documents/Al%27s%20Files",
                "cTag": "\"c:{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx},0\"",
                "size": 6566266651,
                "createdBy": {
                    "user": {
                        "email": "RKilo@example.com",
                        "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx8",
                        "displayName": "Roger Kilo"
                    }
                },
                "lastModifiedBy": {
                    "user": {
                        "email": "RKilo@example.com",
                        "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                        "displayName": "Roger Kilo"
                    }
                },
                "parentReference": {
                    "driveId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                    "driveType": "documentLibrary",
                    "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                    "path": "/drive/root:"
                },
                "fileSystemInfo": {
                    "createdDateTime": "2018-06-04T20:30:42Z",
                    "lastModifiedDateTime": "2018-06-04T20:30:42Z"
                },
                "folder": {
                    "childCount": 1
                }
            },...


        {
        "@microsoft.graph.downloadUrl": "https://example.sharepoint.com/sites/it/_layouts/15/download.aspx?UniqueId=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&Translate=false&tempauth=eyAB4AiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAvaGFub3ZlcnJlc2VhcmNoLnNoYXJlcG9pbnQuY29tQDYyZmZiZjM0LTA1YzYtNDM2Mi05NGQwLTlhN2M3MGM5ZTI2OCIsImlzcyI6IjAwMDAwMDAzLTAwMDAtMGZmMS1jZTAwLTAwMDAwMDAwMDAwMCIsIm5iZiI6IjE1MzM3NTA1NDMiLCJleHAiOiIxNTMzNzU0MTQzIiwiZW5kcG9pbnR1cmwiOiJGbmavsersVWavw3SW9USEN6aWR2czYybldwOEl0ZnFNTUN4QVhneWc4LzEwPSIsImVuZHBvaW50dXJsTGVuZ3RoIjoiMTM1IiwiaXNsb29wYmFjayI6IlRydWUiLCJjaWQiOiJNR1EzWWpJNE4yUXRNR1kzT1MwMFpHav3w@RBr23v2av3r23r23v35n5jtjhtntsgjrt%m9vZnRva2VuIiwic2l0ZWlkIjoiTXprelpEWXhPV0V0TUdVNU9TMDBPV1l5TFdKalltRXROMkl4Tm1Wa016WmhNRFZtIiwiYXBwX2Rpc3BsYXluYW1lIjoiR3JhcGggZXhwbG9yZXIiLCJzaWduaW5fc3RhdGUiOiJbXCJrbXNpXCJdIiwiYXBwaWQiOiJkZThiYzhiNS1kOWY5LTQ4YjEtYThhZC1iNzQ4ZGE3MjUwNjQiLCJ0aWQiOiI2MmZmYmYzNC0wNWM2LTQzNjItOTRkMC05YTdjNzBjOWUyNjgiLCJ1cG4iOiJkZmxvcmVrQGhhbm92ZXJyZXNlYXJjaC5jb20iLCJwdWlkIjoiMTAwMzNGRkZBM0IwNzNDNyIsInNjcCI6Im15ZmlsZXMucmVhZCBhbGxmaWdasVAEWb4tB7ATh4rhtsZmlsZXMud3JpdGUgZ3JvdXAucmVhZCBhbGxzaXRlcy5yZWFkIGFsbHNpdGVzLndyaXRlIiwidHQiOiIyIiwidXNlUGVyc2lzdGVudENvb2tpZSI6bnVsbH0.NkgwczRkYnhNdmtXWEJnMmoya0JGM1VuYm5QYng4N0hTSlNaUU8zcEdnQT0&ApiVersion=2.0",
        "createdDateTime": "2018-01-24T15:25:21Z",
        "eTag": "\"{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx},3\"",
        "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "lastModifiedDateTime": "2018-04-04T16:14:30Z",
        "name": "Mike Roger Plan.doc",
        "webUrl": "https://example.sharepoint.com/sites/it/_layouts/15/Doc.aspx?sourcedoc=%7BB307014A-13EF-4A86-8C16-B2876C141B40%7D&file=Mike%20Roger%20Plan.doc&action=default&mobileredirect=true",
        "cTag": "\"c:{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx},3\"",
        "size": 683008,
        "createdBy": {
            "user": {
                "email": "RKilo@example.com",
                "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                "displayName": "Roger Kilo"
            }
        },
        "lastModifiedBy": {
            "user": {
                "email": "dfoxtrot@example.com",
                "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                "displayName": "Delta Foxtrot"
            }
        },
        "parentReference": {
            "driveId": "bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "driveType": "documentLibrary",
            "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "path": "/drive/root:"
        },
        "file": {
            "mimeType": "application/msword",
            "hashes": {
                "quickXorHash": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
            }
        },
        "fileSystemInfo": {
            "createdDateTime": "2018-01-24T15:25:21Z",
            "lastModifiedDateTime": "2018-04-04T16:14:30Z"
        }
    },...
}

Since I need only the values for "name", "childCount" under "folder" tag, and "mimeType" under the "file" tag, would I need to add all 300+ lines to my script, or would I just take out what I need and not worry about the rest like below?

    public class JSON2Apex {

    public class Folder {
            public Integer childCount {get;set;} 

        public Folder(JSONParser parser) {
            while (parser.nextToken() != System.JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == System.JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != System.JSONToken.VALUE_NULL) {
                        if (text == 'childCount') {
                            childCount = parser.getIntegerValue();
                        } else {
                            System.debug(LoggingLevel.WARN, 'Folder consuming unrecognized property: '+text);
                            consumeObject(parser);
                        }
                    }
                }
            }
        }
    }

    public class File {
        public String mimeType {get;set;} 
        public Hashes hashes {get;set;} 

        public File(JSONParser parser) {
            while (parser.nextToken() != System.JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == System.JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != System.JSONToken.VALUE_NULL) {
                        if (text == 'mimeType') {
                            mimeType = parser.getText();
                        } else if (text == 'hashes') {
                            hashes = new Hashes(parser);
                        } else {
                            System.debug(LoggingLevel.WARN, 'File consuming unrecognized property: '+text);
                            consumeObject(parser);
                        }
                    }
                }
            }
        }
    }

    public class Value {
        public Folder folder {get;set;} 
        public File file {get;set;}
} 

        public Value(JSONParser parser) {
            while (parser.nextToken() != System.JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == System.JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != System.JSONToken.VALUE_NULL) {


    public class Folder {
        public Integer childCount {get;set;} 
}

        public Folder(JSONParser parser) {
            while (parser.nextToken() != System.JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == System.JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != System.JSONToken.VALUE_NULL) {
                        if (text == 'childCount') {
                            childCount = parser.getIntegerValue();                      
                        } else if (text == 'folder') {
                            folder = new Folder(parser);
                        } else if (text == '@microsoft.graph.downloadUrl') {
                            @microsoft_graph_downloadUrl = parser.getText();
                        } else if (text == 'file') {
                            file = new File(parser);
                        } else {
                            System.debug(LoggingLevel.WARN, 'Folder consuming unrecognized property: '+text);
                            consumeObject(parser);
                        }
                    }
                }
            }
        }
    }

I'm also unsure as to how to reference the generated output to find all the values for each parsed type and add them to an array for later processing. Could someone explain this better or point me in the right direction?

3

You can skip parsers entirely here. They make your code more complicated and lower performance. You can just use a simple structure as you have if you remove all your constructors:

public class Value
{
    public Folder folder;
    public File file;
}
public class Folder
{
    public Integer childCount;
}
public class File
{
    public String mimeType;
    public Map<String, String> hashes;
}

Your top level class should also have a definition like the following:

public class MyClass
{
    public Value value;
    public class Value { /* definition as above */ }
    public class Folder { /* definition as above */ }
    public class File { /* definition as above */ }
}

And with this structure you can simply use serialization:

MyClass data = (MyClass)JSON.deserialize(payloadFromQuestion, MyClass.class);
  • Thanks Adrian! I'm a bit of a newbie when it comes to Apex JSON parsing but do I need to include all the generated types or only the ones I'm using? I shortened my JSON2Apex class for brevity. – xorLogic Aug 14 '18 at 15:22
  • @xorLogic You only need to include what you use. Honestly I feel like it's easier to just write your own definitions. It's not super complicated stuff. – Adrian Larson Aug 14 '18 at 15:58
  • Thanks again! Out of curiosity, would it be better to put the MyClass in its own Apex class file and separate it out from my existing class that pulls the JSON from REST? – xorLogic Aug 15 '18 at 16:39
  • I would say it's probably best as a top level class, yes. Also probably obvious, but you should rename it too. :) – Adrian Larson Aug 15 '18 at 16: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.