如何在RestController中使用基于JsonView的两个不同的getter进行序列化?

时间:2019-04-30 00:44:19

标签: java json spring-boot jackson spring-restcontroller

我希望能够基于JsonView序列化对象中的字段。不必是JsonView,这只是我一直在探索的东西。基本上在RestController类上使用@JsonView批注,它将序列化我的POJO。 但是我有一个用户和管理员视图,其中有一个对象:

地图秘密;

对于Admin视图,我希望key:value都显示并序列化,但是对于User,我只希望使用List键,或者如果它更简单,请保留Map但只显示键,并且所有值都切换到'****'4个星号或其他内容。

我考虑过要有两个吸气剂,但是JsonView注释不能像两个吸气剂可以有不同的视图,而杰克逊知道要调用哪个视图那样工作。

我不确定JsonView是这里最好的东西。也许是一种基于视图或某些自定义序列化器进行序列化的JsonGetter方法,但我认为可能会有一种更直接的方法来使用Jackson和很少的批注进行

我想要做的是:

Person.java
Map<String,String> secrets;

这将序列化为(对于管理员):

{
"person":{
  "secrets":{
     "password":"123456",
     "creditCard":"1234 5678 9101"
   }
 }
}

这将序列化为(对于用户):

{
"person":{
  "secrets":{
     "password":"****",
     "creditCard":"****"
   }
 }
}

但是我可以想象的是,


@JsonView(View.User.class)
Map<String,String> getSecrets(){
  this.secrets.forEach(value -> "****") //code would be different but basically setting all values to ****
  return secrets;
}

@JsonView(View.Admin.class)
Map<String,String> getSecrets(){
  //Returning secrets as they should be
  return secrets;
}

1 个答案:

答案 0 :(得分:0)

您可以尝试为对象映射器定义自定义序列化器,以便每当对象映射器用于序列化时,您都可以检查并转换密码和信用卡字段到您选择的值。例如

public class ItemSerializer extends StdSerializer<Item> {

    public ItemSerializer() {
        this(null);
    }

    public ItemSerializer(Class<Item> t) {
        super(t);
    }

    @Override
    public void serialize(
      Item value, JsonGenerator jgen, SerializerProvider provider) 
      throws IOException, JsonProcessingException {

        jgen.writeStartObject();
        jgen.writeNumberField("id", value.id);
        jgen.writeStringField("itemName", value.itemName);
        jgen.writeNumberField("owner", value.owner.id);
        jgen.writeEndObject();
    }
}

您可以提供一个使用该自定义序列化程序的对象映射器,

Item myItem = new Item(1, "theItem", new User(2, "theUser"));
ObjectMapper mapper = new ObjectMapper();

SimpleModule module = new SimpleModule();
module.addSerializer(Item.class, new ItemSerializer());
mapper.registerModule(module);

String serialized = mapper.writeValueAsString(myItem);

在这种情况下,您可以在spring上下文中向自定义序列化器注册objectmapper bean,并使jackson使用您的对象映射器bean。

或使用@JsonSerialize注释,如:

public class Event {
    public String name;

    @JsonSerialize(using = CustomDateSerializer.class)
    public Date eventDate;
}


Public class CustomDateSerializer extends StdSerializer<Date> {

    private static SimpleDateFormat formatter 
      = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");

    public CustomDateSerializer() { 
        this(null); 
    } 

    public CustomDateSerializer(Class<Date> t) {
        super(t); 
    }

    @Override
    public void serialize(
      Date value, JsonGenerator gen, SerializerProvider arg2) 
      throws IOException, JsonProcessingException {
        gen.writeString(formatter.format(value));
    }
}

引用:

https://www.baeldung.com/jackson-json-view-annotation

https://www.baeldung.com/jackson-custom-serialization