2012-06-17 20 views
2

我使用Spring的RestTemplate消耗Chargify API,使用JSON作爲有效負載格式。它一直很順利,但是當我嘗試獲取一組對象時,它失敗了。例如,考慮以下因素:JsonMappingException:當前令牌不是START_OBJECT(需要展開根名稱'Transaction []'),但START_ARRAY

Transaction[] transactions = restTemplate.getForObject(
     CHARGIFY_ENDPOINT + "/subscriptions/{subscription}/transactions.json", 
     Transaction[].class, 
     subscriptionId 
    ); 

實際GET會突破微細,爲的JSON響應:

[ { "transaction" : { "amount_in_cents" : 3006, 
    "created_at" : "2012-06-17T16:32:05-04:00", 
    "ending_balance_in_cents" : 0, 
    "id" : 17283728, 
    "kind" : null, 
    "memo" : "", 
    "payment_id" : null, 
    "product_id" : 120387, 
    "subscription_id" : 1947292, 
    "success" : true, 
    "transaction_type" : "payment", 
    "type" : "Payment" 
     } }, 
    { "transaction" : { "amount_in_cents" : 5900, 
    "created_at" : "2012-06-17T16:32:05-04:00", 
    "ending_balance_in_cents" : 3006, 
    "id" : 17283727, 
    "kind" : "baseline", 
    "memo" : "Professional Plan (06/17/2012 - 07/17/2012)", 
    "payment_id" : 17283728, 
    "product_id" : 120387, 
    "subscription_id" : 1947292, 
    "success" : true, 
    "transaction_type" : "charge", 
    "type" : "Charge" 
     } }, 
    { "transaction" : { "amount_in_cents" : -2894, 
    "created_at" : "2012-06-17T16:32:03-04:00", 
    "ending_balance_in_cents" : -2894, 
    "id" : 17283726, 
    "kind" : "prorated", 
    "memo" : "", 
    "payment_id" : null, 
    "product_id" : 120387, 
    "subscription_id" : 1947292, 
    "success" : null, 
    "transaction_type" : "adjustment", 
    "type" : "Adjustment" 
     } }, 
    { "transaction" : { "amount_in_cents" : 2900, 
    "created_at" : "2012-06-17T15:17:07-04:00", 
    "ending_balance_in_cents" : 0, 
    "id" : 17281084, 
    "kind" : null, 
    "memo" : "", 
    "payment_id" : null, 
    "product_id" : 120386, 
    "subscription_id" : 1947292, 
    "success" : true, 
    "transaction_type" : "payment", 
    "type" : "Payment" 
     } }, 
    { "transaction" : { "amount_in_cents" : 2900, 
    "created_at" : "2012-06-17T15:17:06-04:00", 
    "ending_balance_in_cents" : 2900, 
    "id" : 17281083, 
    "kind" : "baseline", 
    "memo" : "Standard Plan (06/17/2012 - 07/17/2012)", 
    "payment_id" : 17281084, 
    "product_id" : 120386, 
    "subscription_id" : 1947292, 
    "success" : true, 
    "transaction_type" : "charge", 
    "type" : "Charge" 
     } } 
] 

然而,當傑克遜試圖反序列化JSON,它導致JsonMappingException: Current token not START_OBJECT (needed to unwrap root name 'Transaction[]'), but START_ARRAY

16:59:12.651 [http-8080-1] DEBUG org.springframework.web.client.RestTemplate - GET request for "https://foobar.chargify.com/subscriptions/1947292/transactions.json" resulted in 200 (OK) 
16:59:12.651 [http-8080-1] DEBUG org.springframework.web.client.RestTemplate - Reading [[Lcom.foobar.chargify.Transaction;] as "application/json;charset=utf-8" using [org.springf[email protected]1ea8dbd] 
16:59:12.662 [http-8080-1] DEBUG org.apache.http.wire - << "[{"transaction":{"type":"Payment","amount_in_cents":3006,"payment_id":null,"memo":"","id":17283728,"created_at":"2012-06-17T16:32:05-04:00","subscription_id":1947292,"kind":null,"ending_balance_in_cents":0,"success":true,"product_id":120387,"transaction_type":"payment"}},{"transaction":{"type":"Charge","amount_in_cents":5900,"payment_id":17283728,"memo":"Professional Plan (06/17/2012 - 07/17/2012)","id":17283727,"created_at":"2012-06-17T16:32:05-04:00","subscription_id":1947292,"kind":"baseline","ending_balance_in_cents":3006,"success":true,"product_id":120387,"transaction_type":"charge"}},{"transaction":{"type":"Adjustment","amount_in_cents":-2894,"payment_id":null,"memo":"","id":17283726,"created_at":"2012-06-17T16:32:03-04:00","subscription_id":1947292,"kind":"prorated","ending_balance_in_cents":-2894,"success":null,"product_id":120387,"transaction_type":"adjustment"}},{"transaction":{"type":"Payment","amount_in_cents":2900,"payment_id":null,"memo":"","id":17281084,"created_at":"2012-06-17T15:17:07-04:00","subscription_id":1947292,"kind":null,"ending_balance_in_cents":0,"success":true,"product_id":120386,"transaction_type":"payment"}},{"transaction":{"type":"Charge","amount_in_cents":2900,"payment_id":17281084,"memo":"Standard Plan (06/17/2012 - 07/17/2012)","id":17281083,"created_at":"2012-06-17T15:17:06-04:00","subscription_id":1947292,"kind":"baseline","ending_balance_in_cents":2900,"success":true,"product_id":120386,"transaction_type":"charge"}}]" 
16:59:12.683 [http-8080-1] DEBUG org.apache.http.impl.conn.SingleClientConnManager - Releasing connection [email protected]ed710 
16:59:12.684 [http-8080-1] DEBUG org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Resolving exception from handler [public void com.foobar.controllers.TestController.viewTransactions(int)]: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Current token not START_OBJECT (needed to unwrap root name 'Transaction[]'), but START_ARRAY 
at [Source: [email protected]; line: 1, column: 1]; nested exception is org.codehaus.jackson.map.JsonMappingException: Current token not START_OBJECT (needed to unwrap root name 'Transaction[]'), but START_ARRAY 
at [Source: [email protected]; line: 1, column: 1] 
16:59:12.686 [http-8080-1] DEBUG org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver - Resolving exception from handler [public void com.foobar.controllers.TestController.viewTransactions(int)]: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Current token not START_OBJECT (needed to unwrap root name 'Transaction[]'), but START_ARRAY 
at [Source: [email protected]; line: 1, column: 1]; nested exception is org.codehaus.jackson.map.JsonMappingException: Current token not START_OBJECT (needed to unwrap root name 'Transaction[]'), but START_ARRAY 
at [Source: [email protected]; line: 1, column: 1] 
16:59:12.686 [http-8080-1] DEBUG org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Resolving exception from handler [public void com.foobar.controllers.TestController.viewTransactions(int)]: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Current token not START_OBJECT (needed to unwrap root name 'Transaction[]'), but START_ARRAY 
at [Source: [email protected]; line: 1, column: 1]; nested exception is org.codehaus.jackson.map.JsonMappingException: Current token not START_OBJECT (needed to unwrap root name 'Transaction[]'), but START_ARRAY 
at [Source: [email protected]; line: 1, column: 1] 

我之前和傑克遜一起遇到過這個問題,經過幾天的研究,我最終走上了一條不同的路線。這次不是一個選擇,我沒有找到解決方案的運氣。

任何想法?我不在乎是否獲得陣列或返回List。我還沒有碰運氣。

在閱讀傑克遜的文檔時,我看到了你應該能夠包裝清單的位置,即new TypeReference<List<Transaction>>(),但我也沒有運氣。

BTW,因爲Chargify如何格式的JSON響應我的RestTemplate配置了一個自定義ObjectMapper,設置這些選項:

configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true); 
configure(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true); 

當我刪除這些選項,沒有JsonMappingException被拋出但是所有的領域由此產生的Transaction對象爲空。

我也想加入這個選項,但它似乎並沒有幫助:

configure(DeserializationConfig.Feature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); 

回答

3

你只需要另一種包裝類型上的事務之上,也請刪除UNWRAP_ROOT_VALUE選項。

的班會沿着這些路線:

public class TransactionHolder { 
    private Transaction transaction; 
... 
} 

public class Transaction { 
    private String amount_in_cents; 
    private String created_at; 
    private int ending_balance_in_cents; 
    private int id; 
    private String kind; 
    private String memo; 
    private int payment_id; 
    private int product_id; 
    private int subscription_id; 
    private boolean success; 
    private String transaction_type; 
    private String type; 
... 
} 

與樣品JSON,我乾淨了以下工作:

ObjectMapper mapper = new ObjectMapper(); 
InputStream is = this.getClass().getResourceAsStream("sample.json"); 
TransactionHolder[] holders = mapper.readValue(is,TransactionHolder[].class); 
+0

謝謝,我還沒來得及尚未進行測試。與此同時,你能解釋爲什麼這需要一個包裝類,但單個事務JSON對象不會 - 即使單個事務JSON對象也被包裝,即。 {「transaction」:{...}}?的確,唯一的區別是數組包含了其中的很多。這對我來說是如此令人困惑。另外,爲什麼這不需要UNWRAP_ROOT_VALUE選項?再次感謝! :) –

+0

其實,它只是爲我點擊! UNWRAP_ROOT_VALUE選項不是必需的,因爲與單個事務JSON對象不同,數組不包含在無名包裝器對象中。所以沒有什麼可以解開的,並且試圖這樣做會拋出我以前遇到的異常。其次,TransactionHolder類是需要的,因爲數組元素沒有UNWRAP_ROOT_ELEMENT等價物;我們必須使用TransactionHolder自己解包它們。我對嗎? –

+0

是的,正好@TheAwnryBear,你沒有一個包裝的根,所以在反序列化時不需要UNWRAP_ROOT_VALUE。在沒有交易持有人的情況下直接填充交易對象,我認爲可以用傑克遜來完成,但不知道如何離手。 –