JSON DeserializeUntyped Issue – Resolving JSON DeserializeUntyped Function Shortening Response String

I have the following string as a response from a HttpResponse variable using its getBody() function:

{"data":{"chat":[{"speaker":"Speaker 0","startTime":"0.16","message":"for technology positions so that you know your parties four digit extension you may dial it at anytime for a dial by name directory press pound"},{"speaker":"Speaker 1","startTime":"12.04","message":"from member of your team"}],"wordTime":{"for":[{"from":0.16,"to":0.32},{"from":7.93,"to":8.02}],"technology":[{"from":0.32,"to":1.02}],"positions":[{"from":1.11,"to":1.59}],"so":[{"from":1.59,"to":1.7}],"that":[{"from":3.36,"to":3.49}],"you":[{"from":3.49,"to":3.58},{"from":5.59,"to":5.68}],"know":[{"from":3.58,"to":3.73}],"your":[{"from":3.73,"to":3.88},{"from":12.82,"to":13.05}],"parties":[{"from":3.88,"to":4.22}],"four":[{"from":4.35,"to":4.55}],"digit":[{"from":4.55,"to":4.86}],"extension":[{"from":4.86,"to":5.44}],"may":[{"from":5.68,"to":5.77}],"dial":[{"from":5.77,"to":6.15},{"from":8.07,"to":8.38}],"it":[{"from":6.15,"to":6.25}],"at":[{"from":6.25,"to":6.38}],"anytime":[{"from":6.38,"to":6.91}],"a":[{"from":8.02,"to":8.07}],"by":[{"from":8.38,"to":8.51}],"name":[{"from":8.51,"to":8.76}],"directory":[{"from":8.76,"to":9.34}],"press":[{"from":9.61,"to":10.02}],"pound":[{"from":10.09,"to":10.47}],"from":[{"from":12.04,"to":12.2}],"member":[{"from":12.2,"to":12.5}],"of":[{"from":12.5,"to":12.59}],"team":[{"from":13.09,"to":13.42}]},"audioDuration":13.608,"convertedAudioSize":13869,"status":1}}

I converted the string into a Map<String,Object> using the following code:

Map<String,Object> mappedResponse = (Map<String,Object>)JSON.deserializeUntyped(response.getBody());

I obtained the field data inside an Object value:

Object value = (Object) mappedResponse.get('data');

And the problem starts when I want to get the wordTime element inside the Object the String has been shortened from:

"wordTime":{"for":[{"from":0.16,"to":0.32},{"from":7.93,"to":8.02}],"technology":[{"from":0.32,"to":1.02}],"positions":[{"from":1.11,"to":1.59}],"so":[{"from":1.59,"to":1.7}],"that":[{"from":3.36,"to":3.49}],"you":[{"from":3.49,"to":3.58},{"from":5.59,"to":5.68}],"know":[{"from":3.58,"to":3.73}],"your":[{"from":3.73,"to":3.88},{"from":12.82,"to":13.05}],"parties":[{"from":3.88,"to":4.22}],"four":[{"from":4.35,"to":4.55}],"digit":[{"from":4.55,"to":4.86}],"extension":[{"from":4.86,"to":5.44}],"may":[{"from":5.68,"to":5.77}],"dial":[{"from":5.77,"to":6.15},{"from":8.07,"to":8.38}],"it":[{"from":6.15,"to":6.25}],"at":[{"from":6.25,"to":6.38}],"anytime":[{"from":6.38,"to":6.91}],"a":[{"from":8.02,"to":8.07}],"by":[{"from":8.38,"to":8.51}],"name":[{"from":8.51,"to":8.76}],"directory":[{"from":8.76,"to":9.34}],"press":[{"from":9.61,"to":10.02}],"pound":[{"from":10.09,"to":10.47}],"from":[{"from":12.04,"to":12.2}],"member":[{"from":12.2,"to":12.5}],"of":[{"from":12.5,"to":12.59}],"team":[{"from":13.09,"to":13.42}]}

To

wordTime={a=({from=8.02, to=8.07}), anytime=({from=6.38, to=6.91}), at=({from=6.25, to=6.38}), by=({from=8.38, to=8.51}), dial=({from=5.77, to=6.15}, {from=8.07, to=8.38}), digit=({from=4.55, to=4.86}), directory=({from=8.76, to=9.34}), extension=({from=4.86, to=5.44}), for=({from=0.16, to=0.32}, {from=7.93, to=8.02}), four=({from=4.35, to=4.55}), ...}]

And when I receive the value of that object on visualForce I'm getting the shortened string.

How can I avoid this situation?

Thanks in advance.

UPDATE:

This is the code of the function that gets the response:

public static RqaCallLogObject getCallLogSerializer(HttpResponse response){
        RqaCallLogObject callLog = new RqaCallLogObject();
        if(response.getStatusCode() == RqaConstants.SUCCESS){
            Map<String,Object> mappedResponse = (Map<String,Object>)JSON.deserializeUntyped(response.getBody());
            Object value = (Object) mappedResponse.get('data');
            Map<String,Object> mappedValue = (Map<String,Object>)value;

            System.debug('mappedResponse: ' + mappedResponse);
            System.debug('response body: ' + response.getBody());

            callLog.audioDuration = Decimal.valueOf(String.valueOf(mappedValue.get('audioDuration')));
            callLog.convertedAudioSize = Integer.valueOf(String.valueOf(mappedValue.get('convertedAudioSize')));
            callLog.wordTime = mappedValue.get('wordTime');
            callLog.chat = String.valueOf(mappedValue.get('chat'));
            callLog.status = Integer.valueOf(String.valueOf(mappedValue.get('status')));
            callLog.message = '';
        }
        return callLog;
    }

The visualForce code that I'm using is a javascript remoting function that receives as a result the callLog variable, so I guess it's not too important here since the issue is happening in Apex

Best Answer

The problem is not that your string is being cut off, it's that you're processing the data incorrectly. A System.debug statement automatically trims large objects so they don't consume the entire log file. The problem is that you're messing up the JSON data with how you're parsing the JSON. You need to fix your RqaCallLogObject so it reflects the proper data structure, or just return the raw data from the callout and JSON-parse on the client-side.


Parsing On Client

public static String getCallLogSerializer(HttpResponse response){
  return response.getBody();
}

function remoteActionCallback(response, event) {
  var results = JSON.parse(response);
  ...

Parsing In Apex Code

class ChatData {
  String speaker;
  String startTime;
  String message;
}
class MainData {
  Decimal audioDuration;
  List<ChatData> chat;
  Long convertedAudioSize;
  Integer status;
  Map<String, List<Map<String, Decimal>>> wordTime;
}
class DataWrapper {
  MainData data;
}

Which you can then parse explicitly:

public static MainData getCallLogSerializer(HttpResponse response);
  // ... other checks here
  DataWrapper result = (DataWrapper)JSON.deserialize(response.getBody(), DataWrapper.class);
  return result.data;
}
Related Topic