2015-05-13 15 views
13

Tôi đang sử dụng Spring 4 MVC với Jackson 2 cho dịch vụ của mình. Đối với một trong những hoạt động tôi có một đối tượng yêu cầu có một thuộc tính mà trường hợp lạc đà hàng đầu từ đây chỉ là một bức thư dài:Tại sao Jackson 2 không nhận ra chữ cái đầu tiên nếu từ trường hợp lạc đà hàng đầu chỉ là một chữ cái dài?

private String aLogId; 

Lớp này có thu khí đặt tên một cách thích hợp và setters:

public String getALogId() { return aLogId; } 
public void setALogId(String aLogId) { this.aLogId = aLogId; } 

Tuy nhiên, khi tôi cố gắng để gửi một yêu cầu đến dịch vụ này bằng cách sử dụng tài sản tương ứng JSON:

{"aLogId":"This is a log id"} 

tôi nhận được một phản ứng 500 từ Spring framework nói lĩnh vực này không được công nhận và lớp điều khiển của tôi là không bao giờ được gọi là:

Không thể đọc JSON: Trường không được nhận "aLogId" (lớp

Tuy nhiên, khi tôi thay đổi "L" để giảm trường hợp, yêu cầu được deserialized như mong đợi và lớp điều khiển của tôi là hit:

{"alogId":"This is a log id"} 

tại sao Jackson hy vọng "L" là trường hợp thấp hơn khi nó rõ ràng là từ thứ hai trong quy ước trường hợp lạc đà cho thuộc tính và dự định trong trường hợp trên? Có phải vì từ đầu tiên chỉ là một chữ cái dài không?

Có các thuộc tính khác trong đối tượng yêu cầu trong đó từ đầu tiên nhiều hơn một chữ cái và những thuộc tính đó không đối mặt với cùng một vấn đề này với sự không phù hợp trong trường hợp.

+0

đó sẽ là một lỗi thú vị. những gì về một chữ cái duy nhất ở giữa, giống như 'logAId' - nó sẽ thất bại? – ZhongYu

+2

Vấn đề này sẽ biến mất nếu bạn đổi tên bạn getter và setter thành 'setaLogId' và' getaLogId'. Điều đó bay trong khuôn mặt của công ước mặc dù. Có chắc chắn là một cái gì đó 'buggy' khi bạn có những chữ cái duy nhất. – Leon

Trả lời

20

Vấn đề bạn đang thấy là do Jackson sử dụng quy ước đặt tên Java Bean, để tìm ra các thuộc tính Json trong một lớp Java.

Dưới đây là một số reference của sự cố cụ thể mà bạn thấy, đề xuất không được viết hoa không trong hai chữ cái đầu tiên trong trường của bạn. Nếu bạn sử dụng một IDE như IntelliJ hoặc che khuất và để cho các IDE tạo ra setters cho bạn, bạn sẽ nhận thấy sự giống nhau "hành vi" xảy ra, bạn sẽ kết thúc với các phương pháp sau:

public void setaLogId(String aLogId) { 
    this.aLogId = aLogId; 
} 

public String getaLogId() { 
    return aLogId; 
} 

Do đó, khi bạn thay đổi chữ "L" xuống chữ thường Jackson có thể tìm ra trường mà bạn muốn lập bản đồ.

Có nói trên, bạn vẫn có cách thay thế để sử dụng tên trường "aLogId" và làm cho Jackson hoạt động tất cả những gì bạn phải làm là sử dụng chú thích @JsonProperty với số trong đó.

@JsonProperty("aLogId") 
private String aLogId; 

Các mã kiểm tra sau là để hiển thị như thế nào điều này sẽ làm việc:

import com.fasterxml.jackson.annotation.JsonProperty; 
import com.fasterxml.jackson.databind.ObjectMapper; 

public class Test { 

    @JsonProperty("aLogId") 
    private String aLogId; 

    public void setaLogId(String aLogId) { 
     this.aLogId = aLogId; 
    } 

    public String getaLogId() { 
     return aLogId; 
    } 

    public static void main(String[] args) { 

     ObjectMapper objectMapper = new ObjectMapper(); 

     Test test = new Test(); 

     test.setaLogId("anId"); 

     try { 
      System.out.println("Serialization test: " + objectMapper.writeValueAsString(test)); 


      String json = "{\"aLogId\":\"anotherId\"}"; 

      Test anotherTest = objectMapper.readValue(json, Test.class); 

      System.out.println("Deserialization test: " +anotherTest.getaLogId()); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 
} 

Kết quả của bài kiểm tra là:

Serialization test: {"aLogId":"anId"}

Deserialization test: anotherId

+1

Điều này giúp ích. Mặc dù tò mò, trong Java Bean spec 8.8, họ thực sự đề cập đến nếu hai chữ cái đầu tiên là chữ hoa họ để nó một mình, vì vậy có vẻ Jackson nên chọn cái này là ALogId thay vì alogId. Vì vậy, Jackson là deviating từ Java Bean spec sau đó? Dù bằng cách nào, đây là một câu trả lời tuyệt vời và chỉ cho tôi đúng hướng. Cảm ơn và chấp nhận. – Hazok

+0

Tôi đang sử dụng Jackson 2.8.8 và tôi có cùng một vấn đề. Nhưng khi tôi thử giải pháp của bạn (anotating với @JsonProperty ("aLogId") trường "aLogId"), tôi nhận được hai trường JSON: { \t "aLogId": "anId", \t "alogId": "anId" } Vì vậy, trường được nhân đôi, không đúng! Bất kỳ ai trong cùng một tình huống? – Alberthoven

+0

Một giải pháp tuyệt vời. Cảm ơn rất nhiều – Murwa

0

hiểu biết của tôi là mà Jackson sử dụng theo mặc định là conventio đặt tên riêng của nó n, rất gần, nhưng không hoàn toàn giống với quy ước đặt tên Java Bean. Một tùy chọn MapperFeature, MapperFeature.USE_STD_BEAN_NAMING, được thêm vào trong Jackson 2.5.0 để yêu cầu Jackson sử dụng quy ước đặt tên Java Bean - xem Jackson Issue 653. Đối với tính tương thích ngược, giá trị mặc định cho MapperFeature.USE_STD_BEAN_NAMING là sai.

1

Điều này đã hiệu quả đối với tôi; @JsonProperty chú thích trên getters!

import com.fasterxml.jackson.annotation.JsonProperty; 

public class PaytmRequestJson { 
    private String ORDERID; 
    private String MID; 
    private String CHECKSUMHASH; 

    @JsonProperty("ORDERID") 
    public String getORDERID() { 
     return ORDERID; 
    } 

    public void setORDERID(String ORDERID) { 
     this.ORDERID = ORDERID; 
    } 

    @JsonProperty("MID") 
    public String getMID() { 
     return MID; 
    } 

    public void setMID(String MID) { 
     this.MID = MID; 
    } 

    @JsonProperty("CHECKSUMHASH") 
    public String getCHECKSUMHASH() { 
     return CHECKSUMHASH; 
    } 

    public void setCHECKSUMHASH(String CHECKSUMHASH) { 
     this.CHECKSUMHASH = CHECKSUMHASH; 
    } 
} 
Các vấn đề liên quan