【问题标题】:Jackson: how to prevent field serialization [duplicate]杰克逊:如何防止字段序列化[重复]
【发布时间】:2012-02-25 03:23:18
【问题描述】:

我有一个带有密码字段的实体类:

class User {
    private String password;

    //setter, getter..
}

我希望在序列化期间跳过此字段。但它仍然应该能够反序列化。这是必需的,以便客户端可以向我发送新密码,但无法读取当前密码。

我如何与 Jackson 一起完成这项工作?

【问题讨论】:

  • 你不想序列化它,但你想能够反序列化它?那是不可能的,我会说。如果您不将 cookie 放入盒子中,您将无法从该盒子中检索它。
  • @Traroth:但我可以放一个新的 cookie。我只是在寻找一个方便的注释,但这肯定可以手工完成。
  • 快速评论:从技术上讲,完全有可能使用一个 setter(即使是私有的也会自动检测到),而只是省略访问器(没有公共字段或 getter)。也可以在getter上加@JsonIgnore,在setter上加@JsonProperty,这样就不会序列化,但可以反序列化。
  • 您介意接受这个问题的答案吗? (您的其他几个人已经有几年了,也仍然未被接受......请考虑审查!):) 完全披露 - 我对这些问题没有任何答案。

标签: java json jackson


【解决方案1】:

您可以将其标记为@JsonIgnore

在 1.9 中,您可以添加 @JsonIgnore 为 getter,@JsonProperty 为 setter,使其反序列化但不序列化。

【讨论】:

  • @JsonIgnore 也可以防止反序列化。对于瞬态 - 我会检查一下。
  • 在 1.9 中,您可以添加 @JsonIgnore 为 getter,@JsonProperty 为 setter,使其反序列化但不序列化。
  • StaxMan 的评论应该是答案,不是吗?那为什么还是评论……!..?
  • transient 似乎对我不起作用,我将字段“transient”标记为我不希望它被序列化/反序列化。
  • 这个答案之前建议使用transient(如private transient String password;)但transient fields with public getters are ignored除非启用MapperFeature.PROPAGATE_TRANSIENT_MARKER
【解决方案2】:

除了@JsonIgnore,还有其他几种可能:

  • 使用JSON Views 有条件地过滤掉字段(默认情况下,不用于反序列化;在 2.0 中将可用,但您可以对序列化、反序列化使用不同的视图)
  • @JsonIgnoreProperties 上课可能有用

【讨论】:

    【解决方案3】:

    说明 StaxMan 所说的,这对我有用

    private String password;
    
    @JsonIgnore
    public String getPassword() {
        return password;
    }
    
    @JsonProperty
    public void setPassword(String password) {
        this.password = password;
    }
    

    【讨论】:

    • 你使用哪个 Json 依赖?这不适用于 com.fasterxml.jackson
    • 谢谢! @JsonIgnore 在球场上似乎没有必要。
    • com.fasterxml.jackson.annotation.JsonIgnore from jackson-annotations-.jar
    • 我已经尝试过了,但它对我不起作用。我使用 v2.8。有什么帮助吗?
    【解决方案4】:

    transient 是我的解决方案。谢谢!它是 Java 原生的,避免您添加另一个特定于框架的注释。

    【讨论】:

    • 如果你的属性真的是瞬态的,而不是涉及 ORM,例如....发现 @JsonIgnore 在我的情况下更有趣,虽然我会被锁定到杰克逊,但这是一个很好的权衡
    • 如果您创建自己的注解并让 JsonIgnore 和 JacksonAnnotationsInside 对其进行注解,则不必锁定杰克逊。这样,如果你改变序列化器,你只需要改变你自己的注解。
    【解决方案5】:

    简单的方法是注释你的 getter 和 setter。

    这里是修改为排除纯文本密码的原始示例,但随后注释了一个仅将密码字段作为加密文本返回的新方法。

    class User {
    
        private String password;
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @JsonIgnore
        public String getPassword() {
            return password;
        }
    
        @JsonProperty("password")
        public String getEncryptedPassword() {
            // encryption logic
        }
    }
    

    【讨论】:

      【解决方案6】:

      你应该问为什么你需要一个公共的 getter 方法来获取密码。 Hibernate 或任何其他 ORM 框架将使用私有 getter 方法。检查密码是否正确,可以使用

      public boolean checkPassword(String password){
        return this.password.equals(anyHashingMethod(password));
      }
      

      【讨论】:

      • 我实际上认为这是考虑解决方案的最佳方式。将您需要的东西设为私有并从对象本身控制它们更有意义。
      【解决方案7】:

      Jackson 2.6 开始,可以将属性标记为只读或只写。这比破解两个访问器上的注释并将所有信息保存在一个地方更简单:

      public class User {
          @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
          private String password;
      }
      

      【讨论】:

      • 这是一个很棒的解决方案,简单,有效。谢谢。
      • 是的。谢谢你。出于某种原因,setter 上的普通@JsonProperty 和getter 上的@JsonIgnore 绝对不适合我。我不知道为什么,但这钉住了它。谢谢。
      • StackOverflow 应该提出多个赞成票,每次我忘记这个注释时,都会回复你的答案,谢谢,朋友。
      【解决方案8】:

      Jackson 有一个名为 SimpleBeanPropertyFilter 的类,它有助于在序列化和反序列化期间过滤字段;不是全球性的。我想这就是你想要的。

      @JsonFilter("custom_serializer")
      class User {
          private String password;
      
          //setter, getter..
      }
      

      然后在你的代码中:

      String[] fieldsToSkip = new String[] { "password" };
      
      ObjectMapper mapper = new ObjectMapper();
      
      final SimpleFilterProvider filter = new SimpleFilterProvider();
      filter.addFilter("custom_serializer",
                  SimpleBeanPropertyFilter.serializeAllExcept(fieldsToSkip));
      
      mapper.setFilters(filter);
      
      String jsonStr = mapper.writeValueAsString(currentUser);
      

      这将防止password 字段被序列化。此外,您将能够按原样反序列化 password 字段。只要确保没有对 ObjectMapper 对象应用过滤器即可。

      ObjectMapper mapper = new ObjectMapper();
      User user = mapper.readValue(yourJsonStr, User.class);    // user object does have non-null password field
      

      【讨论】:

        【解决方案9】:

        设置变量为

        @JsonIgnore

        这允许 json 序列化程序跳过变量

        【讨论】:

          猜你喜欢
          • 2021-04-02
          • 1970-01-01
          • 1970-01-01
          • 2021-12-02
          • 2013-07-10
          • 2012-12-27
          • 2015-01-29
          • 2013-08-16
          相关资源
          最近更新 更多