3

I am writing a callout in Apex with returns a JSON file with a field that does not have a consistent type. The JSON returned is quite complicated, so I have been trying to read the JSON with a Apex Class structure within salesforce, but this struggles with a varying field type. Is there any way to deal with this in Apex? The location of this varying field (in a fairly simple object list) makes me wonder if I could read only this list as a string so only have to use a nextToken etc for this section? simplified JSON and class structure below. value is the field that varies in type.

`

{
  "users": [
    {
      "id": 461774,
      "email": "test@test.co.uk",
      "name": "test Student",
      "sub_network_ids": [
        18307
      ],
      "custom_attributes": [
        {
          "id": 2310,
          "name": "isReady",
          "value": true,
          "type": "CustomizableAttribute::Boolean"
        },
        {
          "id": 2323,
          "name": "othernames",
          "value": "something",
          "type": "CustomizableAttribute::Text"
        }
      ]
    }
  ]

}`

Code:

public class HivebriteUserList{
    public List<HivebriteUserRecords> users;
}

public class HivebriteUserRecords{
    public String name;
    public String email;
    public List<HivebriteUserCustomAtt> custom_attributes;
    public List<Integer> sub_network_ids;

}

public class HivebriteUserCustomAtt{
    public String id;
    public String name;
    public String value;
}
7

For this situation, I would use JSON.deserializeUntyped that returns nested maps (for objects) and lists (for arrays). That allows the platform code to deal with all JSON related issues (such as escaping and syntax checking) without you having to write any code (such as the hard to get right nextToken stuff).

Your job is then to check what is in the maps -get using the names you expect - and lists and convert them to whatever data structure you want e.g. the classes you list. You are able to randomly walk about the model as you like rather than having to think about handling the nodes from first to last as you would with the JSONParser class.

If the variation is only by the type of a field, then you can store the value in an Object type property in your data structure:

public class HivebriteUserCustomAtt{
    public String id;
    public String name;
    public Object value;
}

and handle the various types elsewhere.

Or if you want to look at the types straight after parsing use e.g.:

Object value = m.get('value');
if (value instanceOf String) {
    String s = (String) value;
    ...
} else if (value instanceOf Boolean) {
    Boolean b = (Boolean) value;
    ...
} ...
| improve this answer | |
  • Great answer - thank you. If necessary, then the deserializeUntyped sounds like a good solution. I have already written a fair amount of code before coming across this problem so I think ideally just changing the value type to object would be best for me, but I unfortunately get the error 'Apex Type unsupported in JSON: Object'. Is this game over for this approach? – Anthony Mealand Oct 25 '18 at 9:56
  • @AnthonyMealand Yeah if you supply the parser a class then it infers the type parsing from the type of the property and can't do that for Object. (Or rather whoever developed the code decided Object didn't make sense even though it arguably does.) But if you use the deserializeUntyped you can just directly assign from the get method to the Object property in your code. – Keith C Oct 25 '18 at 12:00

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.