Home > Back-end >  Dynamically replacing values in JSON response with Spring Boot and Thymeleaf
Dynamically replacing values in JSON response with Spring Boot and Thymeleaf

Time:12-06

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;
}
  • Related