【问题标题】:When is the @JsonProperty property used and what is it used for?何时使用 @JsonProperty 属性以及它的用途是什么?
【发布时间】:2012-09-17 00:16:02
【问题描述】:

这个 bean 的“状态”:

public class State {

    private boolean isSet;

    @JsonProperty("isSet")
    public boolean isSet() {
        return isSet;
    }

    @JsonProperty("isSet")
    public void setSet(boolean isSet) {
        this.isSet = isSet;
    }

}

使用 ajax 'success' 回调通过网络发送:

        success : function(response) {  
            if(response.State.isSet){   
                alert('success called successfully)
            }

这里需要注解@JsonProperty 吗?使用它有什么好处? 我想我可以删除这个注释而不会造成任何副作用。

https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations 上阅读此注释我不知道何时需要使用?

【问题讨论】:

标签: java ajax jackson


【解决方案1】:

这是一个很好的例子。我使用它来重命名变量,因为 JSON 来自 .Net 环境,其中属性以大写字母开头。

public class Parameter {
  @JsonProperty("Name")
  public String name;
  @JsonProperty("Value")
  public String value; 
}

这会正确解析到/从 JSON:

"Parameter":{
  "Name":"Parameter-Name",
  "Value":"Parameter-Value"
}

【讨论】:

  • String 成员变量不能重命名为正确大小写,所以 public String name;成为公共字符串名称; ?
  • 是的,它们可以,但是在 Java 环境中,这使得它们不符合编码标准。更多的是关于我的迂腐,这是一个真正的编码问题,但它是@JsonProperty 注释的实际使用的一个很好但简单的例子。
  • 这个注解可以用于Double类型的成员吗?我只是想知道类型是否必须是 String 或 JSON 支持的任何类型?可以是任何类型吗?@OldCurmudgeon
  • @Dreamer 是的。类型无关紧要。这只会影响名称
  • @Pavan - 这与命名无关。我你应该检查你的二传手。
【解决方案2】:

我认为 OldCurmudgeon 和 StaxMan 都是正确的,但这里有一个简单的例子回答你。

@JsonProperty(name),告诉 Jackson ObjectMapper 将 JSON 属性名称映射到带注释的 Java 字段的名称。

//example of json that is submitted 
"Car":{
  "Type":"Ferrari",
}

//where it gets mapped 
public static class Car {
  @JsonProperty("Type")
  public String type;
 }

【讨论】:

  • 类名是否应该与JSON的根元素相同。这对我不起作用。
【解决方案3】:

现在它的价值……除了通常的序列化和反序列化之外,JsonProperty 还用于指定变量的 getter 和 setter 方法。例如,假设您有这样的有效负载:

{
  "check": true
}

还有一个反序列化器类:

public class Check {

  @JsonProperty("check")    // It is needed else Jackson will look got getCheck method and will fail
  private Boolean check;

  public Boolean isCheck() {
     return check;
  }
}

那么在这种情况下需要 JsonProperty 注释。但是,如果您在类中也有一个方法

public class Check {

  //@JsonProperty("check")    Not needed anymore
  private Boolean check;

  public Boolean getCheck() {
     return check;
  }
}

也请查看此文档: http://fasterxml.github.io/jackson-annotations/javadoc/2.3.0/com/fasterxml/jackson/annotation/JsonProperty.html

【讨论】:

    【解决方案4】:

    如果没有注释,推断的属性名称(从 JSON 匹配)将是“set”,而不是 - 似乎是意图 - “isSet”。这是因为根据 Java Beans 规范,“isXxx”和“setXxx”形式的方法被认为意味着有逻辑属性“xxx”需要管理。

    【讨论】:

    • 这个是问题中给出的具体案例的正确答案
    【解决方案5】:

    如您所知,这完全是关于序列化和淡化对象。假设有一个对象:

    public class Parameter {
      public String _name;
      public String _value; 
    }
    

    这个对象的序列化是:

    {
      "_name": "...",
      "_value": "..."
    }
    

    变量名直接用于序列化数据。如果您要从系统实现中删除系统 api,在某些情况下,您必须在序列化/反序列化中重命名变量。 @JsonProperty 是一个元数据,用于告诉序列化程序如何序列化对象。它用于:

    • 变量名
    • 访问(读、写)
    • 默认值
    • 必需/可选

    来自示例:

    public class Parameter {
      @JsonProperty(
            value="Name",
            required=true,
            defaultValue="No name",
            access= Access.READ_WRITE)
      public String _name;
      @JsonProperty(
            value="Value",
            required=true,
            defaultValue="Empty",
            access= Access.READ_WRITE)
      public String _value; 
    }
    

    【讨论】:

      【解决方案6】:

      添加 JsonProperty 还可以确保安全,以防有人决定要更改其中一个属性名称而没有意识到相关类将被序列化为 Json 对象。如果他们更改属性名称,JsonProperty 会确保它将在 Json 对象中使用,而不是属性名称。

      【讨论】:

        【解决方案7】:

        除了上面所有的答案,不要忘记文档中说的部分

        可用于将非静态方法定义为 逻辑属性的“setter”或“getter”(取决于它的 签名),或要使用的非静态对象字段(序列化, 反序列化)作为逻辑属性。

        如果您的类中有一个non-static 方法不是传统的getter or setter,那么您可以通过在其上使用注释使其像getter and setter 一样工作。请看下面的例子

        public class Testing {
            private Integer id;
            private String username;
        
            public Integer getId() {
                return id;
            }
        
            public void setId(Integer id) {
                this.id = id;
            }
        
            public String getUsername() {
                return username;
            }
        
            public void setUsername(String username) {
                this.username = username;
            }
        
            public String getIdAndUsername() {
                return id + "." + username; 
            }
        
            public String concatenateIdAndUsername() {
                return id + "." + username; 
            }
        }
        

        当上述对象被序列化后,响应中会包含

        • 来自getUsername()的用户名
        • id 来自getId()
        • idAndUsername 来自getIdAndUsername*

        由于方法getIdAndUsernameget 开头,因此它被视为普通的getter,为什么你可以用@JsonIgnore 进行注释。

        如果您注意到concatenateIdAndUsername 没有返回,那是因为它的名称不是以get 开头,如果您希望该方法的结果包含在响应中,那么您可以使用@JsonProperty("...") 和它如上面突出显示的文档中所述,将被视为正常getter/setter

        【讨论】:

          【解决方案8】:

          除了其他答案之外,如果您在没有无参数构造函数的类中使用 @JsonCreator 注释,@JsonProperty 注释非常重要。

          public class ClassToSerialize {
          
              public enum MyEnum {
                  FIRST,SECOND,THIRD
              }
          
              public String stringValue = "ABCD";
              public MyEnum myEnum;
          
          
              @JsonCreator
              public ClassToSerialize(MyEnum myEnum) {
                  this.myEnum = myEnum;
              }
          
              public static void main(String[] args) throws IOException {
                  ObjectMapper mapper = new ObjectMapper();
          
                  ClassToSerialize classToSerialize = new ClassToSerialize(MyEnum.FIRST);
                  String jsonString = mapper.writeValueAsString(classToSerialize);
                  System.out.println(jsonString);
                  ClassToSerialize deserialized = mapper.readValue(jsonString, ClassToSerialize.class);
                  System.out.println("StringValue: " + deserialized.stringValue);
                  System.out.println("MyEnum: " + deserialized.myEnum);
              }
          }
          

          在这个例子中,唯一的构造函数被标记为@JsonCreator,因此杰克逊将使用这个构造函数来创建实例。但输出是这样的:

          序列化:{"stringValue":"ABCD","myEnum":"FIRST"}

          异常 线程“主” com.fasterxml.jackson.databind.exc.InvalidFormatException:不能 构造实例 ClassToSerialize$MyEnum 来自字符串值'stringValue':值不是声明的枚举之一 实例名称:[FIRST、SECOND、THIRD]

          但是在构造函数中添加@JsonProperty注解之后:

          @JsonCreator
          public ClassToSerialize(@JsonProperty("myEnum") MyEnum myEnum) {
              this.myEnum = myEnum;
          }
          

          反序列化成功:

          序列化:{"myEnum":"FIRST","stringValue":"ABCD"}

          字符串值:ABCD

          我的枚举:FIRST

          【讨论】:

            【解决方案9】:

            来自 JsonProperty javadoc,

            定义逻辑属性的名称,即用于属性的 JSON 对象字段名称。如果 value 为空 String(这是默认值),将尝试使用被注释的字段的名称。

            【讨论】:

              猜你喜欢
              • 2019-02-08
              • 2022-01-31
              • 2023-02-08
              • 1970-01-01
              • 1970-01-01
              • 2013-05-29
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多