Spring Boot 如何将自定义序列化程序全局添加到Jackson并默认使用

t98cgbkg  于 2023-01-13  发布在  Spring
关注(0)|答案(3)|浏览(159)

假设我想将Boolean序列化为Number**(默认情况下)。
我知道我可以一个一个地做

@JsonFormat(shape = Shape.NUMBER)
private Boolean success;

但是我可以"注册"我的定制Serializer吗?这样当我从API返回Object时,类中的Boolean将在json响应中被序列化为Number
我有以下序列化程序

public class MyBooleanSerializer extends JsonSerializer<Boolean> {
    @Override
    public void serialize(
                    Boolean value, 
                    JsonGenerator gen, 
                    SerializerProvider serializers) throws IOException {

        gen.writeString(value ? "1" : "0");

    }
}

我有下面的类

@Data
public class MyResponse {
    private Boolean success;
    private String message;
}

它将被这样使用

@GetMapping("/hello")
public MyResponse hello() {
    Boolean success = true;
    String message = "Hi there";
    return new MyResponse(success, message);
}

当我GET这个API时,我期待这样的响应

{
  success: 1,
  message: "Hi there"
}

我在等着注射一些豆子。我试过了

@Bean
@Primary
ObjectMapper objectMapper() {
    SimpleModule module = new SimpleModule();
    module.addSerializer(new MyBooleanSerializer());
    return new ObjectMapper()
            .setSerializationInclusion(JsonInclude.Include.NON_NULL)
            .registerModule(module);
}

但它不起作用。
我读过this教程,看起来每次我想序列化一个对象时都需要创建jsonMapper。我想要的是每当我从API返回MyResponse时,Boolean被序列化为Number
谢谢。

c9qzyr3d

c9qzyr3d1#

不需要全局序列化程序

,只是为了对布尔字段全局地强制@JsonFormat(shape = Shape.NUMBER)注解。
您可以覆盖应用于布尔字段的全局规则,使用自定义的Shape.NUMBER,这样您就不必在每个类的每个布尔字段中都这样做。
因此,与在每个类的每个字段中为serialization/deserialization

@JsonFormat(shape = Shape.NUMBER)
private Boolean success;

您可以使用以下代码全局执行此操作:

@Bean
public ObjectMapper registerObjectMapper(){
   ObjectMapper mapper = new ObjectMapper();            
   mapper.configOverride(Boolean.class)
         .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.NUMBER));
   mapper.configOverride(boolean.class)
         .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.NUMBER));
   return mapper;
 }

如何在必要时应用全局串行化程序

但是如果您坚持要注册全局序列化程序,以便该格式仅用于序列化而不是反序列化,那么您可以使用以下命令:

@Bean
public ObjectMapper registerObjectMapper(){
    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule("MyBooleanSerializer");
    module.addSerializer(Boolean.class, new MyBooleanSerializer());
    module.addSerializer(boolean.class, new MyBooleanSerializer());
    mapper.registerModule(module);
   
    return mapper;
}

还有

public class MyBooleanSerializer extends JsonSerializer<Boolean> {
    @Override
    public void serialize(
                    Boolean value, 
                    JsonGenerator gen, 
                    SerializerProvider serializers) throws IOException {

        gen.writeString(value ? "1" : "0");

    }
}

有一个陷阱

请仔细查看第二个解决方案

module.addSerializer(Boolean.class, new MyBooleanSerializer());
module.addSerializer(boolean.class, new MyBooleanSerializer());

并且在第一溶液中

.configOverride(Boolean.class)
  .configOverride(boolean.class)

对于Jackson,原语boolean as字段和 Package 器Boolean类需要单独注册,以便能够工作。

xj3cbfub

xj3cbfub2#

可以使用自定义StdSerializer完成,例如

class CustomBooleanSerializer extends StdSerializer<Boolean> {

    public CustomBooleanSerializer(){
        super(Boolean.class);
    }

    @Override
    public void serialize(Boolean value, JsonGenerator generator, SerializerProvider provider) throws IOException {
        generator.writeNumber(value ? 1 : 0);
    }
}

并通过Jackson2ObjectMapperBuilderCustomizer进行配置

@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
  return builder ->
    builder.serializationInclusion(JsonInclude.Include.USE_DEFAULTS) // <-- optional
           .serializers(new CustomBooleanSerializer());
}
31moq8wy

31moq8wy3#

由于使用了序列化程序,布尔值被转换为true或false的形式

public class NumericBooleanSerializer extends JsonSerializer<Boolean> {
    
    public void serialize(Boolean b, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeNumber(b ? 1 : 0);
    }
}

将布尔值序列化为1或0。

相关问题