A way to String.format() an json array string with a single %s

431 views Asked by At

I'm trying to see if there is a way to format a json array string with a single %s, without the backslashes. The API I'm working on attaches this formatted string as a body parameter and sends it over to the server. When the server gets it, there are backslahes in the string. I would need this string to be without the escape characters.

The constant looks like this:

final String REQUEST_PARAMS = "{\"params\":{\"details\":{\"param1\":\"%s\",\"param2\":\"%s\",\"extraParams\":\"%s\"}}}"; 

This is the snippet for converting the json array to string:

...
ObjectMapper mapper = new ObjectMapper(); 
String extraParams = mapper.writeValueAsString(params.getExtraParams()); // this looks like: [{"hostValue": "id1", "portNumber": "name1"}, {...}] for example.
    
String formattedParams = String.format(REQUEST_PARAMS, "param1", "param2", extraParams); // {"params":{"details":{"param1":"param1","param2":"param2","extraParams":"[{"hostValue": "id1", "portNumber": "name1"}]"}}}
...

However, when this gets sent over to the backend API, it looks like:

{"params":{"details":{"param1":"param1","param2":"param2","extraParams":[{\"hostValue\": \"id1\", \"portNumber\": \"name1\"}]}}}.

If I format a string by specifying having %s for each field in the json array, it works without the backslashes (e.g hostValue: %s, portNumber: %s). However, this wont work since there is a possibility that there is an unknown parameter in the json array that is not predefined in the constant (e.g sqlPORTNumber).

I want to make sure there is no escape characters being sent over to the server, is there a way to achieve this? Any insights would be greatly appreciated!

1

There are 1 answers

0
VGR On BEST ANSWER

Don’t use String.format. It is not the right tool for this. It will not cover the various needs of well-formed JSON syntax. Using String.format will eventually result in invalid JSON.

Use your ObjectMapper to convert data to JSON:

Map<String, Object> details = new HashMap<>();
details.put("param1", param1Value);
details.put("param2", param2Value);
details.put("extraParams", params.getExtraParams());

Map<String, Object> params = new HashMap<>();
params.put("details", details);

Map<String, Object> responseBody = new HashMap<>();
responseBody.put("params", params);

String formattedResponse = mapper.writeValueAsString(responseBody);

Instead of creating three Maps, a better design is to create bean classes:

public class Details {
    public String getParam1() { ... }
    public void setParam1(String value) { ... }

    public String getParam2() { ... }
    public void setParam2(String value) { ... }

    public ExtraParams getExtraParams() { ... }
    public void setExtraParams(ExtraParams p) { ... }
}

public class Params {
    public Details getDetails() { ... }
    public void setDetails(Details d) { ... }
}

public class MyResponse {
    public Params getParams() { ... }
    public void setParams(Params p) { ... }
}

/* ... */

Details details = new Details();
details.setParam1(param1Value);
details.setParam2(param2Value);
details.setExtraParams(params.getExtraParams());

Params params = new Params();
params.setDetails(details);

MyResponse response = new MyResponse();
response.setParams(params);

String formattedResponse = mapper.writeValueAsString(response);