Search code examples
javajsonspringrestresttemplate

How can I correctly send a HashMap that contains both Doubles and Strings in its values when posting to a API in JSON


I'm using Springs rest template to post some data in JSON to an API. Unfortunately the values of my HashMap contain both doubles and Strings.

I've attempted to use a HashMap with the following datatype: HashMap, however I've found that the resulting JSON looks something like the following instead:

{
  "VARIABLE_1":"0.0000",
  "VARIABLE_2":"True",
  "VARIABLE_3":"String"
 }

Unfortunately the API I'm posting to isn't processing these doubles correctly as they are being sent as Strings. Is there someway I can be agnostic about the datatypes still but have HttpEntity format doubles correctly.

Here is an example of the code I'm actually using:

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.CommonsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

...

public void postMethod(HashMap<String,Object> input) {

    CommonsClientHttpRequestFactory requestFactory = new CommonsClientHttpRequestFactory();
    restTemplate.setRequestFactory(requestFactory);
    HttpEntity<HashMap<String,Object>> requestEntity = new HttpEntity<>(input, headers);

    ResponseEntity<Result> result = restTemplate.postForEntity(uri, requestEntity, Result.class);
    Result result = result.getBody();
}

Solution

  • You can create a custom JSON body by directly accessing the Jackson library that Spring uses:

    import com.fasterxml.jackson.databind.node.JsonNodeFactory;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    
    ...
    
    public void postMethod(HashMap<String,Object> input) {
        ObjectNode jsonBody = JsonNodeFactory.instance.objectNode();
        for (Map.Entry<String, Object> entry : input.entrySet())
        {
            String key = entry.getKey();
            Object value = entry.getValue();
    
            if (value instanceof Double)
                jsonBody.put(key, (Double)value);
            else if (value instanceof Boolean)
                jsonBody.put(key, (Boolean)value);
            else
                jsonBody.put(key, value);
        }
    
        // ... make headers ...
    
        HttpEntity<String> requestEntity = new HttpEntity<>(jsonBody.toString(), headers);
    
        // ... make the post request ...
    }
    

    The only dumb part is that you have to cast your value before you call put() because otherwise Java calls the put(String, Object) method override.