使用 Spring Boot 和 Thymeleaf 动态替换 JSON 响应中的值

Dynamically replacing values in JSON response with Spring Boot and Thymeleaf

使用 Spring 引导我想为外部 API 实施模拟服务。由于此模拟仅用于测试,因此我希望事情尽可能简单。外部APIreturns一个JSON类似这个:

{
  "customer": {
    "email": "foo@bar.com"
  },
  "result": {
    "status_code": 100
  },
  "transaction": {
    "amount": 100,
    "currency": "EUR",
    "order_no": "123456"
  }
}

控制器:

@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;
}

所以基本上,应用程序从文件中加载一个 JSON 字符串,并在响应中 returns 它。现在我想用动态值替换 amount 和 JSON 中的 order_no,如下所示:

{
  "customer": {
    "email": "foo@bar.com"
  },
  "result": {
    "status_code": 100
  },
  "transaction": {
    "amount": ${amount},
    "currency": "EUR",
    "order_no": "${orderNumber}"
  }
}

我的第一个想法是为此使用 Thymeleaf,因此我创建了以下配置:

@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;
    }
}

但我不知道如何实际“运行”模板,以便 sampleResourceString 被动态值替换。

或者 Thymeleaf 可能实际上是某种“矫枉过正”?

考虑到 JSON 的结构非常简单,我会将它们映射到 类 并使用 Jackson。例如:

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 + ...
}

然后你可以这样写一个控制器:

@ResponseBody // You need the @ResponseBody annotation or annotate the controller with @RestController
@GetMapping(value = "/api")
public DummyResponse mockMethod() {
    return new DummyResponse(
        new DummyResponseCustomer("foo@bar.com"),
        new DummyResponseResult(100),
        new DummyResponseTransaction(new BigDecimal("100"), "EUR", "123456")
    );
}

这使得想出动态值变得相当容易,而无需使用模板引擎(如 Thymeleaf)或处理 I/O。除此之外,您可能已经在某处使用了这些 类 来使用外部 API.

也许只使用 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;
}