Source:
<code>static JSONObject generateJsonDiff(JSONObject cur, JSONObject changedTo, JSONObject baseOutput, Set<String> includeFields) { if (cur == null) return null; if (changedTo == null) return baseOutput; Iterator<String> keys = changedTo.keys(); String key; Object value; JSONObject output; if (baseOutput != null) output = baseOutput; else output = new JSONObject(); while (keys.hasNext()) { try { key = keys.next(); value = changedTo.get(key); if (cur.has(key)) { if (value instanceof JSONObject) { JSONObject curValue = cur.getJSONObject(key); JSONObject outValue = null; if (baseOutput != null && baseOutput.has(key)) outValue = baseOutput.getJSONObject(key); JSONObject returnedJson; synchronized (syncLock) { <START> returnedJson = generateJsonDiff(curValue, (JSONObject) value, outValue, includeFields); <END> } String returnedJsonStr = returnedJson.toString(); if (!returnedJsonStr.equals("{}")) output.put(key, new JSONObject(returnedJsonStr)); } else if (value instanceof JSONArray) handleJsonArray(key, (JSONArray) value, cur.getJSONArray(key), output); else if (includeFields != null && includeFields.contains(key)) output.put(key, value); else { Object curValue = cur.get(key); if (!value.equals(curValue)) { if (curValue instanceof Integer && !"".equals(value)) { if ( ((Number)curValue).doubleValue() != ((Number)value).doubleValue()) output.put(key, value); } else output.put(key, value); } } } else { if (value instanceof JSONObject) output.put(key, new JSONObject(value.toString())); else if (value instanceof JSONArray) handleJsonArray(key, (JSONArray) value, null, output); else output.put(key, value); } } catch (JSONException e) { e.printStackTrace(); } } return output; }</code><technical_language>curious, do synchronize this line method</technical_language>

Target:
static JSONObject generateJsonDiff(JSONObject cur, JSONObject changedTo, JSONObject baseOutput, Set<String> includeFields) { if (cur == null) return null; if (changedTo == null) return baseOutput; Iterator<String> keys = changedTo.keys(); String key; Object value; JSONObject output; if (baseOutput != null) output = baseOutput; else output = new JSONObject(); while (keys.hasNext()) { try { key = keys.next(); value = changedTo.get(key); if (cur.has(key)) { if (value instanceof JSONObject) { JSONObject curValue = cur.getJSONObject(key); JSONObject outValue = null; if (baseOutput != null && baseOutput.has(key)) outValue = baseOutput.getJSONObject(key); JSONObject returnedJson; returnedJson = generateJsonDiff(curValue, (JSONObject) value, outValue, includeFields); String returnedJsonStr = returnedJson.toString(); if (!returnedJsonStr.equals("{}")) output.put(key, new JSONObject(returnedJsonStr)); } else if (value instanceof JSONArray) handleJsonArray(key, (JSONArray) value, cur.getJSONArray(key), output); else if (includeFields != null && includeFields.contains(key)) output.put(key, value); else { Object curValue = cur.get(key); if (!value.equals(curValue)) { if (curValue instanceof Integer && !"".equals(value)) { if ( ((Number)curValue).doubleValue() != ((Number)value).doubleValue()) output.put(key, value); } else output.put(key, value); } } } else { if (value instanceof JSONObject) output.put(key, new JSONObject(value.toString())); else if (value instanceof JSONArray) handleJsonArray(key, (JSONArray) value, null, output); else output.put(key, value); } } catch (JSONException e) { e.printStackTrace(); } } return output; }