Using Spring Boot I'd like to implement a mock service for an external API. As this mock is only used for testing, I'd like to keep things as simple as possible. The external API returns a JSON similar to this one:
{
"customer": {
"email": "[email protected]"
},
"result": {
"status_code": 100
},
"transaction": {
"amount": 100,
"currency": "EUR",
"order_no": "123456"
}
}
And the controller:
@Value("classpath:/sample.json")
private Resource sampleResource;
@GetMapping(value = "/api")
public String mockMethod() throws IOException {
final InputStream inputStream = sampleResource.getInputStream();
final String sampleResourceString = StreamUtils.copyToString(sampleResource, StandardCharsets.UTF_8);
return sampleResourceString;
}
So basically, the application loads a JSON string from a file and returns it in the response. Now I'd like to replace the amount
and the order_no
in the JSON with a dynamic value, like this:
{
"customer": {
"email": "[email protected]"
},
"result": {
"status_code": 100
},
"transaction": {
"amount": ${amount},
"currency": "EUR",
"order_no": "${orderNumber}"
}
}
My first idea was to use Thymeleaf for this, so I created the following configuration:
@Configuration
@RequiredArgsConstructor
public class TemplateConfiguration {
private final ApplicationContext applicationContext;
@Bean
public SpringResourceTemplateResolver templateResolver() {
final SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("/templates");
templateResolver.setSuffix(".json");
templateResolver.setTemplateMode(TemplateMode.TEXT);
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
return templateEngine;
}
}
But I'm stuck how I can actually "run" the templating so that the sampleResourceString
is replaced with the dynamic values.
Or is Thymeleaf maybe actually some kind of "overkill" for this?
CodePudding user response:
Considering that the JSON has quite a simple structure, I would map them out to classes and use Jackson. For example:
public class DummyResponse {
private DummyResponseCustomer customer;
private DummyResponseTransaction transaction;
private DummyResponseResult result;
// TODO: Getters Setters ...
}
public class DummyResponseTransaction {
private BigDecimal amount;
private String currency;
@JsonProperty("order_no")
private String orderNumber;
// TODO: Getters Setters ...
}
And then you could write a controller like this:
@ResponseBody // You need the @ResponseBody annotation or annotate the controller with @RestController
@GetMapping(value = "/api")
public DummyResponse mockMethod() {
return new DummyResponse(
new DummyResponseCustomer("[email protected]"),
new DummyResponseResult(100),
new DummyResponseTransaction(new BigDecimal("100"), "EUR", "123456")
);
}
This makes it fairly easy to come up with dynamic values and without having to use a templating engine (like Thymeleaf) or having to handle I/O. Besides that, you probably have these classes somewhere already to consume the external API.
CodePudding user response:
Maybe just use String.replace()
?
@GetMapping(value = "/api")
public String mockMethod() throws IOException {
final InputStream inputStream = sampleResource.getInputStream();
final String sampleResourceString = StreamUtils.copyToString(sampleResource, StandardCharsets.UTF_8);
String replacedString = sampleResourceString.replace("${amount}", ...)
.replace("${orderNumber}", ...);
return replacedString;
}