【问题标题】:How to have different @JsonProperty based on environment in spring boot如何在Spring Boot中根据环境拥有不同的@JsonProperty
【发布时间】:2022-01-11 23:55:14
【问题描述】:

我有一个类被用作访问另一个服务的请求。

它有几个像下面这样的字段。

public class RequestClass {

  @JsonProperty("123")
  private String name;

  @JsonProperty("124")
  private String email;

  @JsonProperty("129")
  private String mobile;

}

上游服务需要字段id为123、124、129等的请求。

测试和生产环境的这些字段 id 会有所不同。

除了使用不同的RequestClass,还有什么更好的方法吗?

【问题讨论】:

  • 你说的field id是什么意思?字段 name、字段 value 还是其他?请为几个环境提供预期的 json。

标签: java json spring-boot jackson resttemplate


【解决方案1】:

您可以创建一个配置类,在其中根据您的环境跟踪实际 id 并使用 jackson 的 @JsonAnyGetter 映射它们。

例如,如果您有以下application.properties(我在这里使用multi-document props,但您也可以在每个配置文件中使用application.properties):

spring.profiles.active=dev
#---
spring.config.activate.on-profile=dev
application.requestClass.nameId=123
#---
spring.config.activate.on-profile=test
application.requestClass.nameId=456

然后,您将创建您的配置类(我使用 Lombok 的 @Data 作为 getter/setter):

@Configuration
@Data
public class RequestClassConfig {

    @Value("${application.requestClass.nameId}")
    private String nameId;

    @PostConstruct
    public void postConstruct() {
        RequestClass.config = this;
    }
}

最后是你的 DTO,@JsonAnyGetter:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class RequestClass {

    public static RequestClassConfig config;

    @JsonIgnore
    private String name;

    @JsonAnyGetter
    public Map<String, Object> any() {
        final var map = new HashMap<String, Object>();

        map.put(config.getNameId(), this.name);
        return map;
    }

}

请注意,您可以对其余的道具执行相同的操作,为简洁起见,我省略了这些。

现在进行快速测试:

@SpringBootApplication
public class App {

    public static void main(String[] args) throws JsonProcessingException {
        SpringApplication.run(App.class, args);
        final var mapper = new ObjectMapper();
        final var req = new RequestClass();
        req.setName("test");

        System.out.println(mapper.writeValueAsString(req));
    }

}

这将打印 如果dev 配置文件处于活动状态,则{"123":"test"} 到控制台 和 {"456":"test"} 如果test 配置文件处于活动状态。

【讨论】:

  • 非常感谢。它解决了我的问题?
  • 您能否解释一下反序列化部分,因为反序列化时值变为空
  • 这是我试图实现的,但我无法按照上述用例来塑造它。我必须将 {"123":"test"} 映射到 {"name":"test"}。我已经在 any() 方法中删除了地图并在外面声明了它。在做 RequestClass req = new Mapper().readValue("{"123":"test"}", Request.class);这些值被存储在地图中,但“名称”字段仍然为空。你能帮忙吗? @eol
  • 啊,我明白了,我们需要为该用例构建一个自定义解串器。你能发布一个新问题吗?我会在那里添加代码。
猜你喜欢
  • 1970-01-01
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
  • 2016-11-15
  • 1970-01-01
  • 2018-03-22
  • 1970-01-01
  • 2018-06-30
相关资源
最近更新 更多