When the value of a non-required parameter is empty, our wsclient http request bodies currently displays the null/empty element in json as:

{not-required-empty-parameter: "null"};

And in XML as:

<not-required-empty-parameter />

We are looking for an option to remove these elements from the request body when the value of the parameter is not defined in rules. The web-services we are integrating does not accept empty elements and is returning errors. It requires that if the element is empty, exclude it from the request body.

Comments

freddura’s picture

I've been able to hard code this functionality after applying the patch provided by Comment #17 on Issue #1280332...

This is a code snippet from wsclient/wsclient_rest/wsclient_rest.inc lines 61-95 after applying the patch:

  public function call($operation_name, $arguments) {
    $operation = $this->service->operations[$operation_name];
    $operation_url = isset($operation['url']) ? $operation['url'] : '';
    // Replace argument patterns in the operation URL
    foreach ($arguments as $key => $value) {
      if (strpos($operation_url, '@' . $key) !== FALSE) {
        $operation_url = str_replace('@' . $key, $value, $operation_url);
        unset($arguments[$key]);
      }
    }
    $client = $this->client();
    $type = isset($operation['type']) ? $operation['type'] : 'GET';
    $data = NULL;
    if (isset($operation['data'])) {
      $data = $arguments[$operation['data']];
      unset($arguments[$operation['data']]);
    }
    // Services module compliance: post fields should be in the $data array
    // instead of $arguments.
    if ($type == 'POST') {
      $data = array_merge((array) $data, $arguments);
    }
    try {       
    $response = $client->execute(new HttpClientRequest($this->service->url . $operation_url, array(
        'method' => $type,
        'parameters' => $arguments,
        'data' => $data,
      )));
      return $response;
    }
    catch (HttpClientException $e) {
      throw new WSClientException('Error invoking the REST service %name, operation %operation: %error', array('%name' => $this->service->label, '%operation' => $operation_name, '%error' => $e->getMessage()));
    }
  }<a href="/node/1280332">Issue #1280332</a>

And this is a code snippet from wsclient/wsclient_rest/wsclient_rest.inc lines 61-110 after adding my code, bringing in this new functionality:

  public function call($operation_name, $arguments) {
    $operation = $this->service->operations[$operation_name];
    $operation_url = isset($operation['url']) ? $operation['url'] : '';
    // Replace argument patterns in the operation URL.
    foreach ($arguments as $key => $value) {
      if (strpos($operation_url, '@' . $key) !== FALSE) {
        $operation_url = str_replace('@' . $key, $value, $operation_url);
        unset($arguments[$key]);
      }
    }
    $client = $this->client();
    $type = isset($operation['type']) ? $operation['type'] : 'GET';
    $data = NULL;
    if (isset($operation['data'])) {
      $data = $arguments[$operation['data']];
      unset($arguments[$operation['data']]);
    }
    // Services module compliance: post fields should be in the $data array
    // instead of $arguments.
    if ($type == 'POST') {
      $data = array_merge((array) $data, $arguments);
    }
    try {  

    // This function removes empty parameters from the data
     function array_non_empty_data($input) {
       if (!is_array($input)) {
         return $input;
       }
       $non_empty_data = array();
       foreach ($input as $key => $value) {
         if($value) {
         $non_empty_data[$key] = array_non_empty_data($value);
         }
       }
       return $non_empty_data;
     }
  
  	$response = $client->execute(new HttpClientRequest($this->service->url . $operation_url, array(
        'method' => $type,
        'parameters' => $arguments,
        'data' => array_non_empty_data($data),
      )));
      return $response;
    }
    catch (HttpClientException $e) {
      throw new WSClientException('Error invoking the REST service %name, operation %operation: %error', array('%name' => $this->service->label, '%operation' => $operation_name, '%error' => $e->getMessage()));
    }
  }

This can still use work for the purpose making it an option in the UI as some situations may not require this behavior.