0

am trying to parse the below JSON request to Apex class. The challenge here is that one of the node "match" in the JSON is suppose to be an array but the external system sends it as a String. I would need to convert the string to array and parse it. The approach that I followed was to remove the double quotes for the match node and use JSOn2Apex heroku app - https://json2apex.herokuapp.com/ to generate the response Apex class and use JSON.deserialize(jsonString, apexType) to deserialize the result.

{
  "response": [
    {
      "tmodule": "trans",
      "resultList": [
        {
          "output": [
            {
               "var1": 8119,
              "var2": "Foundational",
              "var3": "",
              "match": "[{\"type\":\"Record\",\"tableName\":\"model_score\",\"AnId\":\"103708\",\"frequency\":\"Weekly\",\"Type\":\"trigger\",\"country\":\"Argentina,Australia,Austria,Canada,Finland,France,Germany,HongKong,India,Italy,Japan,Mexico,Netherlands,NewZealand,Singapore,Spain,Sweden,Taiwan,Thailand,UK,US\",\"fields\":[{\"name\":\"wwwf\",\"type\":\"sdad\",\"alias\":\"\",\"doc\":\"CM15 represents the 15 digit card number embossed on the plastic card\"},{\"name\":\"Score\",\"type\":\"Double\",\"alias\":\"\",\"doc\":\"Score value generated from the execution of the model\"},{\"name\":\"outp_var1\",\"type\":\"Double\",\"alias\":\"\",\"doc\":\"amount\"},{\"name\":\"outp_var3\",\"type\":\"String\",\"alias\":\"SegmentId\",\"doc\":\"modelId\"}],\"segmentIdColumn\":\"output_var3\",\"segmentIdDetails\":[{\"segmentId\":\"SM1\",\"description\":\"amount>=100000 and amount<115000\"},{\"segmentId\":\"SM2\",\"description\":\"amount>=100000 and amount<150000\"},{\"segmentId\":\"SM3\",\"description\":\"Other\"}]}]",
              "table": "stname",
              "create_date": 3243252345
            }
          ],
          "SId": 1234,
          "Sdescp": "XXXXXX"
        }
      ]
    }
  ],
  "error": false,
  "errorResponse": null
}

However I had trouble with parsing the "match" node for which I had to tweak the response apex class a bit like this. I had to add another parser to replace the double quotes. For some reason it worked. However I was not able to use JSON.deserialize(jsonString, apexType) to deserialize the JSON instead I had to call the Parse method directly which is in Response Apex Class.

 private static List<Match> arrayOfMatch(System.JSONParser parseObj) {
        List<Match> res = new List<Match>();
        if (parseObj.getCurrentToken() == null){
            parseObj.nextToken();
        }
        System.JSONParser parser2 = System.JSON.createParser(parseObj.getText().replace('\\',''));
        while (parser2.nextToken() != System.JSONToken.END_ARRAY) {
            res.add(new Match(parser2));
        }
        return res;
    }

Is there a better way to do this? Given how the JSON attribute match is represent as a String instead of an array. What is the best approach in this case.

4
  • 2
    You already asked it here? how is this different? salesforce.stackexchange.com/questions/245490/… Jan 8, 2019 at 18:23
  • 1
    Agree, the previous question is very similar to this except here I wanted to describe what I did to solve the problem and wanted to know if this is an ok approach or is there any other suggestion. Is deserializeUntyped(jsonString) the way to go in these kind of JSON structures?
    – SfdcBat
    Jan 8, 2019 at 18:29
  • You should have just edited your original question then.
    – Adrian Larson
    Jan 8, 2019 at 18:54
  • Agree with that. I can mark the other one as duplicate of this question.
    – SfdcBat
    Jan 8, 2019 at 18:56

1 Answer 1

2

This is how I would do it:

String s = '{"ints":"[1,2,3]"}'; // Sample JSON

Class test {
    private String ints; // since it is returned as a string, store it as a string
                         // make it private to protect it

    // public method converts it to the desired type
    public List<Integer> getInts() {
        return (List<Integer>) json.deserialize(ints, List<Integer>.class);
    }

    public void setInts(List<Integer> ints) {
        this.ints = json.serialize(ints);
    }
}

// Deserialize into your class
test t = (Test) JSON.deserialize(s, test.class);

// call the public method
List<Integer> ints = t.getInts();

// verify results
system.debug(string.valueOf(ints));

ints.add(12); // Manipulate the list

t.setInts(ints); // Add the list back to the class

system.debug(string.valueOf(t.getInts())); // verify results

Except for instead of integers, you would use your Match class that you created with json2apex.

As always review this post for more information on working with JSON.

4
  • So do you think I should mix both Json2Apex and the above approach just for the node "match"? ANy comments about the approach I took to use a new parser (parser2) inside the existing parser. Will it not be the right way to do?
    – SfdcBat
    Jan 8, 2019 at 18:46
  • 1
    My comment is stop relying on JSON 2Apex. It creates a situation where you don't actually know what you're doing. Instead, view this post to learn about how to convert json to apex yourself. I write all the classes I use for rest apis by hand.
    – gNerb
    Jan 8, 2019 at 18:48
  • Wholeheartedly agree that you should reduce your reliance on this external tool. It's all well and good if it saves you time doing work you could do yourself anyway. But if you use it as a crutch to prevent learning how to do the work yourself, it is a hindrance rather than a benefit.
    – Adrian Larson
    Jan 8, 2019 at 18:56
  • I used JSON2Apex to save some time and I was successful using it earlier. So felt it was a reliable tool that can be used but dint realize that it is not flexible with any type of JSON structure specifically the once I have where Array is a String. Thanks for the suggestions.
    – SfdcBat
    Jan 8, 2019 at 19:11

You must log in to answer this question.

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