Spring Boot 预处理 JSON 数据

sis*_*red 5 java serialization spring json spring-boot

我有一个 RESTful Spring Boot API,它有一个注册端点。

在我的@RestController班级中,我编写了一个简单的字符串值预处理器,用于修剪和仅用null值替换空白字符串。

  @InitBinder
  public void blankStringBinder(WebDataBinder dataBinder) {
    dataBinder.setDisallowedFields("password", "confirmPassword");
    StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true);
    dataBinder.registerCustomEditor(String.class, stringTrimmerEditor);
  }
Run Code Online (Sandbox Code Playgroud)

但是当我将 Postman 的数据作为 raw 提交时JSON,修剪编辑不会发生。我在blankStringBinder方法中放置了一个断点,我看到它在每个传入请求上都会被调用。

WebDataBinder似乎工作form-data。有没有办法让它也适用于原始JSON数据?

Séb*_*ado 7

如果您只想在几个String字段上执行此操作,请首先创建一个自定义JsonDeserializer

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;

public class EmptyToNullCustomDeserializer extends JsonDeserializer<String> {
    @Override
    public String deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
        JsonNode node = jp.readValueAsTree();
        if (node.textValue().isEmpty()) {
            return null;
        }
        return node.textValue();
    }
}
Run Code Online (Sandbox Code Playgroud)

String然后在每个POJO上添加此注释: @JsonDeserialize(using = EmptyToNullCustomDeserializer.class)。例如 :

@JsonDeserialize(using = EmptyToNullCustomDeserializer.class)
private String content;
Run Code Online (Sandbox Code Playgroud)

编辑:

如果您有很多String想要预处理的字段,那么对每个字段进行注释可能会非常麻烦。

作为替代方案,您可以预处理所有 String字段,而无需对它们进行注释。为此,您必须首先进行修改EmptyToNullCustomDeserializer,使其父类为 Jacksons StdDeserializer

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import org.springframework.stereotype.Component;

@Component
public class EmptyToNullCustomDeserializer extends StdDeserializer<String> {
    protected EmptyToNullCustomDeserializer() {
        super(String.class);
    }

    @Override
    public String deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
        JsonNode node = jp.readValueAsTree();
        if (node.textValue().isEmpty()) {
            return null;
        }
        return node.textValue();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后创建此组件,以便通过将上述反序列化器添加到配置来自定义 Jackson 对象映射器:

import java.util.List;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.stereotype.Component;

@Component
public class JacksonConfiguration {

    @Autowired
    private EmptyToNullCustomDeserializer emptyToNullCustomDeserializer;

    @Primary
    @Bean
    public Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder(List<Jackson2ObjectMapperBuilderCustomizer> customizers) {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        for (Jackson2ObjectMapperBuilderCustomizer customizer : customizers) {
            customizer.customize(builder);
        }
        return builder;
    }

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer addEmptyToNullStringDeserialization() {
        return new Jackson2ObjectMapperBuilderCustomizer() {
            @Override
            public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
                jacksonObjectMapperBuilder.deserializerByType(String.class, emptyToNullCustomDeserializer);
            }

        };
    }
}
Run Code Online (Sandbox Code Playgroud)