@JsonProperty มีการใช้คุณสมบัติใดและจะใช้เมื่อใด


183

ถั่วนี้ 'รัฐ':

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 : function(response) {  
            if(response.State.isSet){   
                alert('success called successfully)
            }

จำเป็นต้องใช้คำอธิบายประกอบ @JsonProperty ที่นี่หรือไม่ ประโยชน์ของการใช้มันคืออะไร? ฉันคิดว่าฉันสามารถลบคำอธิบายประกอบนี้ได้โดยไม่ทำให้เกิดผลข้างเคียงใด ๆ

อ่านเกี่ยวกับ annotion นี้ได้ที่https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotationsฉันไม่ทราบว่าจะต้องใช้เมื่อใด


คำตอบ:


238

นี่เป็นตัวอย่างที่ดี ฉันใช้มันเพื่อเปลี่ยนชื่อตัวแปรเพราะ JSON มาจาก.Netสภาพแวดล้อมที่คุณสมบัติเริ่มต้นด้วยตัวอักษรตัวพิมพ์ใหญ่

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

แยกวิเคราะห์จาก JSON ได้อย่างถูกต้อง:

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

1
ตัวแปรสมาชิก String ไม่สามารถเปลี่ยนชื่อเป็นกรณีที่ถูกต้องได้ดังนั้นชื่อ String สาธารณะ กลายเป็นชื่อสตริงสาธารณะ ?
บลูสกาย

14
ใช่พวกเขาทำได้ แต่ในสภาพแวดล้อม Java ที่ทำให้พวกเขาไม่ตรงกับมาตรฐานการเข้ารหัส มันเกี่ยวกับคนเดินถนนของฉันมากกว่าเรื่องการเขียนโค้ดจริง แต่มันก็เป็นตัวอย่างที่ดีและเรียบง่ายของการใช้@JsonPropertyหมายเหตุประกอบ
OldCurmudgeon

คำอธิบายประกอบนี้สามารถใช้กับสมาชิกประเภทได้Doubleหรือไม่ ฉันแค่สงสัยว่าจะต้องเป็นStringประเภทหรือประเภทที่สนับสนุน JSON หรือไม่ เป็นประเภทใดก็ได้ @OldCurmudgeon
Dreamer

3
@Dreamer ใช่ ประเภทไม่เกี่ยวข้อง สิ่งนี้มีผลกับชื่อเท่านั้น
OldCurmudgeon

1
@Pavan - มันไม่มีอะไรเกี่ยวข้องกับการตั้งชื่อ ฉันเดาว่าคุณควรตรวจสอบผู้ตั้งค่าของคุณ
OldCurmudgeon

44

ฉันคิดว่า OldCurmudgeon และ StaxMan นั้นถูกต้อง แต่นี่เป็นคำตอบประโยคเดียวที่มีตัวอย่างง่าย ๆ สำหรับคุณ

@JsonProperty (ชื่อ) บอกให้ 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 หรือไม่ มันไม่ทำงานสำหรับฉัน
Pavan

39

ดีสำหรับสิ่งที่คุ้มค่าในตอนนี้ ... JsonProperty ยังใช้เพื่อระบุวิธี getter และ setter สำหรับตัวแปรนอกเหนือจากการทำให้เป็นอนุกรมและการดีซีเรียลไลเซชันตามปกติ ตัวอย่างเช่นสมมติว่าคุณมีส่วนของข้อมูลดังนี้:

{
  "check": true
}

และคลาส Deserializer:

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


15

หากไม่มีคำอธิบายประกอบชื่อคุณสมบัติที่สรุป (เพื่อจับคู่จาก JSON) จะเป็น "ชุด" และไม่ใช่ - ตามที่ดูเหมือนจะเป็นเจตนา - "isSet" นี่เป็นเพราะตามข้อกำหนดของ Java Beans วิธีการของรูปแบบ "isXxx" และ "setXxx" ถูกนำมาใช้เพื่อหมายความว่ามีคุณสมบัติเชิงตรรกะ "xxx" ในการจัดการ


1
อันนี้เป็นคำตอบที่ถูกต้องสำหรับกรณีเฉพาะที่ให้ไว้ในคำถาม
Andrew Spencer

6

อย่างที่คุณทราบนี่คือทั้งหมดที่เกี่ยวกับการทำให้เป็นอันดับและทำให้เป็นวัตถุ สมมติว่ามีวัตถุ:

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

การทำให้เป็นอันดับของวัตถุนี้คือ:

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

ชื่อของตัวแปรถูกใช้โดยตรงเพื่อทำให้เป็นอนุกรมข้อมูล หากคุณกำลังจะลบระบบ API ออกจากการนำระบบไปใช้ในบางกรณีคุณต้องเปลี่ยนชื่อตัวแปรในการทำให้เป็นอนุกรม / ดีซีเรียลไลเซชัน @JsonProperty เป็นข้อมูลเมตาที่จะบอก serializer ถึงวิธีการเรียงลำดับวัตถุ มันถูกใช้เพื่อ:

  • ชื่อตัวแปร
  • การเข้าถึง (อ่านเขียน)
  • ค่าเริ่มต้น
  • ต้อง / ไม่จำเป็น

จากตัวอย่าง:

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 ไม่ใช่ชื่อคุณสมบัติ


3

นอกเหนือจากคำตอบอื่น ๆ แล้ว@JsonPropertyคำอธิบายประกอบนั้นสำคัญมากถ้าคุณใช้@JsonCreatorคำอธิบายประกอบในคลาสที่ไม่มีคอนสตรัคเตอร์ที่ไม่มีอาร์กิวเมนต์

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"}

ข้อยกเว้นในเธรด "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: ไม่สามารถสร้างอินสแตนซ์ของ ClassToSerialize $ MyEnum จากค่าสตริง 'stringValue': ค่าไม่ใช่หนึ่งในชื่อตัวอย่างของ Enum ที่ประกาศ: [FIRST, SECOND, THIRD]

แต่หลังจากเพิ่ม@JsonPropertyคำอธิบายประกอบใน Constructor แล้ว:

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

deserialization สำเร็จ:

ต่อเนื่อง: {"myEnum": "FIRST", "stringValue": "ABCD"}

StringValue: ABCD

MyEnum: FIRST


2

นอกจากคำตอบทั้งหมดข้างต้นอย่าลืมส่วนของเอกสารที่กล่าวถึง

คำอธิบายประกอบเครื่องหมายที่สามารถใช้เพื่อกำหนดวิธีการไม่คงที่เป็น "setter" หรือ "getter" สำหรับคุณสมบัติเชิงตรรกะ (ขึ้นอยู่กับลายเซ็นของมัน) หรือเขตข้อมูลวัตถุที่ไม่คงที่จะใช้ (ต่อเนื่อง deserialized) เป็นตรรกะ คุณสมบัติ

หากคุณมีnon-staticวิธีการในชั้นเรียนที่ไม่ใช่แบบธรรมดาgetter or setterคุณสามารถทำให้มันเป็นแบบ a 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*

ตั้งแต่วิธีการที่getIdAndUsernameจะเริ่มต้นด้วยgetแล้วก็ถือว่าเป็น getter @JsonIgnoreปกติดังนั้นเหตุผลที่คุณสามารถใส่คำอธิบายประกอบดังกล่าวกับ

หากคุณสังเกตเห็นconcatenateIdAndUsernameว่าไม่ได้ส่งคืนและนั่นเป็นเพราะชื่อนั้นไม่ได้ขึ้นต้นด้วยgetและหากคุณต้องการให้ผลลัพธ์ของวิธีการนั้นรวมอยู่ในการตอบกลับคุณสามารถใช้งานได้@JsonProperty("...")และจะถือว่าเป็นเรื่องปกติตามgetter/setterที่กล่าวไว้ในเอกสาร .


0

จาก JsonProperty javadoc

กำหนดชื่อของคุณสมบัติเชิงตรรกะเช่นชื่อฟิลด์วัตถุ JSON เพื่อใช้สำหรับคุณสมบัติ หากค่าเป็นสตริงว่าง (ซึ่งเป็นค่าเริ่มต้น) จะพยายามใช้ชื่อของฟิลด์ที่มีคำอธิบายประกอบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.