code: protected JSONObject generateChangedParam() {
      if (totallyOverwrite) {
        HashMap<String, Object> tmp = new HashMap<>();
        tmp.putAll(this.serverData);
  
        // createdAt, updatedAt, objectId is immutable.
        tmp.remove(KEY_CREATED_AT);
        tmp.remove(KEY_UPDATED_AT);
        tmp.remove(KEY_OBJECT_ID);
        return new JSONObject(tmp);
      }
  
      Map<String, Object> params = new HashMap<String, Object>();
      Set<Map.Entry<String, ObjectFieldOperation>> entries = operations.entrySet();
      for (Map.Entry<String, ObjectFieldOperation> entry: entries) {
        //{"attr":{"__op":"Add", "objects":[obj1, obj2]}}
        Map<String, Object> oneOp = entry.getValue().encode();
        params.putAll(oneOp);
      }
  
      if (null != this.acl) {
        AVACL serverACL = generateACLFromServerData();
        if (!this.acl.equals(serverACL)) {
          // only append acl request when modified.
          ObjectFieldOperation op = OperationBuilder.gBuilder.create(OperationBuilder.OperationType.Set, KEY_ACL, acl);
          params.putAll(op.encode());
        }
      }
  
      if (!needBatchMode()) {
        return new JSONObject(params);
      }
  
      List<Map<String, Object>> finalParams = new ArrayList<Map<String, Object>>();
      Map<String, Object> topParams = Utils.makeCompletedRequest(getObjectId(), getRequestRawEndpoint(), getRequestMethod(), params);
      if (null != topParams) {
        finalParams.add(topParams);
      }
  
      for (ObjectFieldOperation ops : this.operations.values()) {
        if (ops instanceof CompoundOperation) {
          List<Map<String, Object>> restParams = ((CompoundOperation)ops).encodeRestOp(this);
          if (null != restParams && !restParams.isEmpty()) {
            finalParams.addAll(restParams);
          }
        }
      }
      Map<String, Object> finalResult = new HashMap<String, Object>(1);
      finalResult.put("requests", finalParams);
  
      return new JSONObject(finalResult);
    }
docs: save/update with server.