4

I have a Custom Object named AppConfig__c and a field named Config__c. In the field I have value as a JSON format. How can I read the value of the JSON field? Below is an example field value:

{"SFObjectNames":[{"Account":{"SFFieldNames":["Industry","Type"]}},{"Addresses":{"SFFieldNames":["Coordinates__c"]}}]}

I have to read this value in Apex class. How can I get the value of SFFieldNames?

2 Answers 2

9

You have a couple options here, if the code will always return the same structure you can create a strongly typed class that will allow you to get the values you want. This tool will parse the json for you and create a class http://json2apex.herokuapp.com/

which results in this.

public class JSON2Apex {

        public class Account {
            public List<String> SFFieldNames;
        }

        public List<SFObjectNames> SFObjectNames;

        public class SFObjectNames {
            public Account Account;
            public Account Addresses;
        }


        public static JSON2Apex parse(String json) {
            return (JSON2Apex) System.JSON.deserialize(json, JSON2Apex.class);
        }
    }

You can call JSON2Apex myClass = JSON2Apex.parse( jsonString) which will parse the json and you can reference it in code.

Another way is to use the JSON class and do System.JSON.deserializeUntyped(json); which returns an Object and then you can cast loop over the object and cast the object to a Map if needed. This is a little more difficult in parsing and if you can use a Strongly Typed class because the structure won't change much, I would recommend that.

Edit: Adding looping for deserializedUntyped

List<Object> newList = List<Object>JSON.deserializeUntyped( jsonString);
for( Object o : newList) {

  Map<String, Object> castedObject = (Map<String, Object>)o;
  List<Object> sffFieldNames = o.get('SFObjectNames');

  // returns "[{"Account":{"SFFieldNames":["Industry","Type"]}},{"Addresses":{"SFFieldNames":["Coordinates__c"]}}]"
  for( Object o1 : sffFieldNames) {

    Map<String, Object> newCast = (Map<String, Object>)o1;
    Object acct = o.get('Account');
    // returns "{"SFFieldNames":["Industry","Type"]}}
  }
}

Basically, the you need to loop over the object, and you can cast to a Map and then you can get the key which returns the object value. and because you have nested array's you'll need to do this multiple times. Might be worth doing some sort of recursion, so it's not hardcoded.

5
  • No. @Mike Havrilla it cannot be strongly typed as it can change. I want it to be dynamic.
    – Ejaz
    Feb 22, 2017 at 14:55
  • I've updated my code to reflect part of the solution that @Martin Lezer also stated. Feb 22, 2017 at 15:14
  • Have u check your code, it's giving syntax error.
    – Ejaz
    Feb 22, 2017 at 15:25
  • ejaz It's more pusedo code, since it would be a full json parser if it was working. My understanding is that you need to dynamically parse the Json, the fundamentals above will get you started, when it's an Array cast to List<Object> when it's a json object you can cast to Map<String, Object>. If you debug those you can see the outputs and handle them appropriately... If you need something quick and more concrete then martinLezur has a workable solution too. (but if that's the case then a Strongly typed class is probably a better way to go.) Feb 22, 2017 at 15:36
  • @Ejaz can you please mark one of the answers as the correct one? Feb 27, 2017 at 14:54
10

Apex provides a JSON class.

You can choose to deserialize your json value in an apex type. Using classes you defined.

You can also deserialize your field without type but in a Map using the deserializeUntyped(jsonString) method.

After that, you will access the properties values by using the keys like this: m.get('SFFieldNames');

UPDATE

Here's what I manage to do for your json:

Map<String, Object> result = (Map<String, Object>)JSON.deserializeUntyped('{"SFObjectNames":[{"Account":{"SFFieldNames":["Industry","Type"]}},{"Addresses":{"SFFieldNames":["Coordinates__c"]}}]}');
List<Object> objectNames = (List<Object>)result.get('SFObjectNames');
List<String> fieldNames = new List<String>();

Map<String, Object> objAccount = (Map<String, Object>)objectNames[0];
Map<String, Object> objAddresses = (Map<String, Object>)objectNames[1];

Map<String, Object> account = (Map<String, Object>)objAccount.get('Account');
Map<String, Object> addresses = (Map<String, Object>)objAddresses.get('Addresses');

for(Object fieldNameObj : (List<Object>)account.get('SFFieldNames')){
    fieldNames.add((String)fieldNameObj);   
}

for(Object fieldNameObj : (List<Object>)addresses.get('SFFieldNames')){
    fieldNames.add((String)fieldNameObj);   
}

System.debug(fieldNames);

NOTE

I strongly recommend using deserialize with types defined as Apex class.

3
  • Hi @Martin Lezer can you provide me with the sample code. I am unable to get your solution.
    – Ejaz
    Feb 22, 2017 at 14:59
  • I have tried your solution but it doesnt seems to be working. Map<String, Object> m = (Map<String, Object>)JSON.deserializeUntyped(configValues); System.debug('JSON DESERIALIZE' + m); System.debug('CONFIG VALUES:' + m.get('SFFieldNames')); In Debug Logs I am gettting null.
    – Ejaz
    Feb 22, 2017 at 15:12
  • @Ejaz I updated my answer. Feb 22, 2017 at 15:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .