2017-01-27 4 views
1

Я работаю над проектом, в котором я интегрируюсь со сторонней службой, которая возвращает ответ JSON. Я использую Jackson для десериализации ответа в Java POJO. Ответ - это объект, который имеет несколько простых полей, которые Джексон может легко проанализировать. Однако ответ также содержит массив с одной записью, которая также является объектом. Когда Джексон пытается десериализовать его, я получаю объект верхнего уровня, содержащий список с единственной записью в списке, однако все поля для одной записи в списке равны нулю. Любая идея, что я делаю неправильно здесь?Jackson: Разбор объекта с массивом объектов

UPDATE: после установки FAIL_ON_UNKNOWN_PROPERTIES в true, я получаю следующую трассировку стека. Все еще не уверен, почему у него возникают проблемы с завернутым объектом «RecurringDetail» в массиве.

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Нераспознанное поле "RecurringDetail" (класс com.adyen.www.models.RecurringDetail), не помеченные как игнорируемые (19 известных свойств: "вариант", "contractTypes" , "tokenDetails", "aliasType", "name", "creationDate", "firstPspReference", "elv", "card", "дополнительные данные", "shopperName", "socialSecurityNumber", "billingAddress", "bank" recurringDetailReference "," paymentMethodVariant "," alias "," acquirer "," acquirerAccount "]) at [Источник: response.json; строка: 5, столбец: 33] (через цепочку ссылок: com.adyen.www.models.RecurringDetailsResult ["details"] -> java.util.ArrayList [0] -> com.adyen.www.models.RecurringDetail [" RecurringDetail "]) на com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from (UnrecognizedPropertyException.java:62) в com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty (DeserializationContext.java:834) на ком. fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty (StdDeserializer.java:1094) на com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty (BeanDeserializerBase.java:1470) на com.fasterxml.jackson. databind.deser.BeanDeserializerBase.handleUnknownVanilla (BeanDeserializerBase.java:1448) at com.fasterxml.jackson.databind.deser.BeanDeserializer .vanillaDeserialize (BeanDeserializer.java:282) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize (BeanDeserializer.java:140) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize (CollectionDeserializer .java: 287) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize (CollectionDeserializer.java:259) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize (CollectionDeserializer.java : 26) в com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize (SettableBeanProperty.java:499) на com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet (MethodProperty.java:101) в com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize (BeanDese rializer.java:276) на com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize (BeanDeserializer.java:140) на com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose (ObjectMapper.java:3798) на com.fasterxml.jackson.databind.ObjectMapper.readValue (ObjectMapper.Java: 2759)

JSON

{ 
"creationDate": "2017-01-26T23:11:20+01:00", 
"details": [ 
    { 
     "RecurringDetail": { 
      "acquirer": "TestPmmAcquirer", 
      "acquirerAccount": "TestPmmAcquirerAccount", 
      "additionalData": { 
       "cardBin": "440000" 
      }, 
      "alias": "B133243153928547", 
      "aliasType": "Default", 
      "card": { 
       "expiryMonth": "8", 
       "expiryYear": "2018", 
       "holderName": "Steve HAll", 
       "number": "0008" 
      }, 
      "contractTypes": [ 
       "RECURRING" 
      ], 
      "creationDate": "2017-01-26T23:11:20+01:00", 
      "firstPspReference": "8524854686798738", 
      "paymentMethodVariant": "visadebit", 
      "recurringDetailReference": "8414854686802111", 
      "variant": "visa" 
     } 
    } 
], 
"invalidOneclickContracts": "false", 
"lastKnownShopperEmail": "[email protected]", 
"shopperReference": "xggZcGauSSG5jP+akIlijQ==" 
} 

Unit Test

public class RecurringDetailResultTest { 

public static ObjectMapper mapper = new ObjectMapper() 
{ 
    private static final long serialVersionUID = -174113593500315394L; 
    { 
     configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
     configure(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS, true); 
     setSerializationInclusion(JsonInclude.Include.NON_NULL); 
    } 
}; 

@Test 
public void testParseRecurringDetailResulte() throws IOException { 

    RecurringDetailsResult result = mapper.readValue(new File("response.json"), new TypeReference<RecurringDetailsResult>(){}); 
    if (result.getDetails() != null && !result.getDetails().isEmpty()) { 
     RecurringDetail detail = result.getDetails().get(0); 
     if (StringUtils.isEmpty(detail.getRecurringDetailReference())) { 
      fail("Recurring detail does not contain any information."); 
     } 
    } else { 
     fail("No result details returned."); 
    } 

} 

} 

Модель (Root объекта)

public class RecurringDetailsResult 
    implements java.io.Serializable { 
private static final long serialVersionUID = 5297684963950973136L; 
private Date creationDate; 
private String shopperReference; 
private List<RecurringDetail> details; 
private String lastKnownShopperEmail; 

@JsonGetter("creationDate") 
public Date getCreationDate () { 
    return this.creationDate; 
} 

@JsonSetter("creationDate") 
public void setCreationDate (Date value) { 
    this.creationDate = value; 
} 

@JsonGetter("shopperReference") 
public String getShopperReference () { 
    return this.shopperReference; 
} 

@JsonSetter("shopperReference") 
public void setShopperReference (String value) { 
    this.shopperReference = value; 
} 

@JsonGetter("details") 
public List<RecurringDetail> getDetails () { 
    return this.details; 
} 

@JsonSetter("details") 
public void setDetails (List<RecurringDetail> value) { 
    this.details = value; 
} 

@JsonGetter("lastKnownShopperEmail") 
public String getLastKnownShopperEmail () { 
    return this.lastKnownShopperEmail; 
} 

@JsonSetter("lastKnownShopperEmail") 
public void setLastKnownShopperEmail (String value) { 
    this.lastKnownShopperEmail = value; 
} 

} 

Модель (объект в массиве, все области этот парень имеет значение null, когда Джексон десериализует JSON)

public class RecurringDetail 
    implements java.io.Serializable { 
private static final long serialVersionUID = 5302883242997268343L; 
private String name; 
private Date creationDate; 
private Card card; 
private ELV elv; 
private Address billingAddress; 
private String additionalData; 
private Name shopperName; 
private String socialSecurityNumber; 
private String recurringDetailReference; 
private BankAccount bank; 
private String alias; 
private String aliasType; 
private TokenDetails tokenDetails; 
private String variant; 
private String paymentMethodVariant; 
private String firstPspReference; 
private List<String> contractTypes; 
private String acquirer; 
private String acquirerAccount; 

@JsonGetter("name") 
public String getName () { 
    return this.name; 
} 

@JsonSetter("name") 
public void setName (String value) { 
    this.name = value; 
} 

@JsonGetter("creationDate") 
public Date getCreationDate () { 
    return this.creationDate; 
} 

@JsonSetter("creationDate") 
public void setCreationDate (Date value) { 
    this.creationDate = value; 
} 

@JsonGetter("card") 
public Card getCard () { 
    return this.card; 
} 

@JsonSetter("card") 
public void setCard (Card value) { 
    this.card = value; 
} 

@JsonGetter("elv") 
public ELV getElv () { 
    return this.elv; 
} 

@JsonSetter("elv") 
public void setElv (ELV value) { 
    this.elv = value; 
} 

@JsonGetter("billingAddress") 
public Address getBillingAddress () { 
    return this.billingAddress; 
} 

@JsonSetter("billingAddress") 
public void setBillingAddress (Address value) { 
    this.billingAddress = value; 
} 

@JsonGetter("additionalData") 
public String getAdditionalData () { 
    return this.additionalData; 
} 

@JsonSetter("additionalData") 
public void setAdditionalData (String value) { 
    this.additionalData = value; 
} 

@JsonGetter("shopperName") 
public Name getShopperName () { 
    return this.shopperName; 
} 

@JsonSetter("shopperName") 
public void setShopperName (Name value) { 
    this.shopperName = value; 
} 

@JsonGetter("socialSecurityNumber") 
public String getSocialSecurityNumber () { 
    return this.socialSecurityNumber; 
} 

@JsonSetter("socialSecurityNumber") 
public void setSocialSecurityNumber (String value) { 
    this.socialSecurityNumber = value; 
} 

@JsonGetter("recurringDetailReference") 
public String getRecurringDetailReference () { 
    return this.recurringDetailReference; 
} 

@JsonSetter("recurringDetailReference") 
public void setRecurringDetailReference (String value) { 
    this.recurringDetailReference = value; 
} 

@JsonGetter("bank") 
public BankAccount getBank () { 
    return this.bank; 
} 

@JsonSetter("bank") 
public void setBank (BankAccount value) { 
    this.bank = value; 
} 

@JsonGetter("alias") 
public String getAlias () { 
    return this.alias; 
} 

@JsonSetter("alias") 
public void setAlias (String value) { 
    this.alias = value; 
} 

@JsonGetter("aliasType") 
public String getAliasType () { 
    return this.aliasType; 
} 

@JsonSetter("aliasType") 
public void setAliasType (String value) { 
    this.aliasType = value; 
} 

@JsonGetter("tokenDetails") 
public TokenDetails getTokenDetails () { 
    return this.tokenDetails; 
} 

@JsonSetter("tokenDetails") 
public void setTokenDetails (TokenDetails value) { 
    this.tokenDetails = value; 
} 

@JsonGetter("variant") 
public String getVariant () { 
    return this.variant; 
} 

@JsonSetter("variant") 
public void setVariant (String value) { 
    this.variant = value; 
} 

@JsonGetter("paymentMethodVariant") 
public String getPaymentMethodVariant () { 
    return this.paymentMethodVariant; 
} 

@JsonSetter("paymentMethodVariant") 
public void setPaymentMethodVariant (String value) { 
    this.paymentMethodVariant = value; 
} 

@JsonGetter("firstPspReference") 
public String getFirstPspReference () { 
    return this.firstPspReference; 
} 

@JsonSetter("firstPspReference") 
public void setFirstPspReference (String value) { 
    this.firstPspReference = value; 
} 

@JsonGetter("contractTypes") 
public List<String> getContractTypes () { 
    return this.contractTypes; 
} 

@JsonSetter("contractTypes") 
public void setContractTypes (List<String> value) { 
    this.contractTypes = value; 
} 

@JsonGetter("acquirer") 
public String getAcquirer () { 
    return this.acquirer; 
} 

@JsonSetter("acquirer") 
public void setAcquirer (String value) { 
    this.acquirer = value; 
} 

@JsonGetter("acquirerAccount") 
public String getAcquirerAccount () { 
    return this.acquirerAccount; 
} 

@JsonSetter("acquirerAccount") 
public void setAcquirerAccount (String value) { 
    this.acquirerAccount = value; 
} 

} 
+0

Я пытался с этим UNWRAP_SINGLE_VALUE_ARRAYS установлен и истинным и ложным. Я также пробовал это с ACCEPT_SINGLE_VALUE_AS_ARRAY, установленным как true, так и false. – Steve

+0

Я установил DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES в true и теперь получаю эту трассировку стека – Steve

+0

Вы можете изменить json? проблема заключается в том, что ваш внешний объект не имеет корневого значения, а ваш внутренний объект. – teacurran

ответ

0

The Самое простое, что я могу сделать, это сделать ваши объекты Java похожими на вашего Json. Поскольку этот Json имеет завернутый внутренний объект, но не внешний объект, вы должны иметь аналогичную упаковку в java. Это не изящно, но работает.

public class RecurringDetailsResult implements java.io.Serializable { 

    private Date creationDate; 
    private String shopperReference; 
    private List<RecurringDetailWrapper> details; 
    private String lastKnownShopperEmail; 

    // getters and setters here. No need for any @JsonGetter or @JsonSetter annotations 
} 


@JsonRootName("RecurringDetail") 
public class RecurringDetailWrapper { 

    @JsonProperty("RecurringDetail") 
    RecurringDetail recurringDetail; 

    public RecurringDetail getRecurringDetail() { 
     return recurringDetail; 
    } 

    public void setRecurringDetail(RecurringDetail recurringDetail) { 
     this.recurringDetail = recurringDetail; 
    } 
} 


public class RecurringDetail implements java.io.Serializable { 
    private static final long serialVersionUID = 5302883242997268343L; 

    private String name; 
    private Date creationDate; 
    private Card card; 
    private AdditionalData additionalData; 
    private String socialSecurityNumber; 
    private String recurringDetailReference; 
    private String alias; 
    private String aliasType; 
    private String variant; 
    private String paymentMethodVariant; 
    private String firstPspReference; 
    private List<String> contractTypes; 
    private String acquirer; 
    private String acquirerAccount; 

    public class AdditionalData { 
     String cardBin; 

     public String getCardBin() { 
      return cardBin; 
     } 

     public void setCardBin(String cardBin) { 
      this.cardBin = cardBin; 
     } 
    } 

    // getters and setters here. No need for any @JsonGetter or @JsonSetter annotations 

} 

Затем в тестовом модуле:

@Test 
public void testParseRecurringDetailResulte() throws IOException { 

    InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("ID41901838.json"); 

    ObjectReader objectReader = mapper.readerFor(RecurringDetailsResult.class); 
    RecurringDetailsResult result = objectReader.readValue(inputStream); 

    if (result.getDetails() != null && !result.getDetails().isEmpty()) { 
     RecurringDetailWrapper detail = result.getDetails().get(0); 
     if (StringUtils.isEmpty(detail.getRecurringDetail().getRecurringDetailReference())) { 
      fail("Recurring detail does not contain any information."); 
     } 
    } else { 
     fail("No result details returned."); 
    } 
} 

я отправил полный рабочий код здесь: https://github.com/teacurran/java-experiments/tree/master/stackoverflow-sandbox/src/main/java/com/wirelust/stackoverflowsandbox/ID41901838

+0

Спасибо. Добавление объекта оболочки к моей модели java работало как шарм. – Steve

0

кажется текущая структура будет работать в ответ JSON, как показано ниже (дополнительный названный слой удаляется)

{ 
"creationDate": "2017-01-26T23:11:20+01:00", 
"details": [ 
    { 
      "acquirer": "TestPmmAcquirer", 
      "acquirerAccount": "TestPmmAcquirerAccount", 
      "additionalData": { 
       "cardBin": "440000" 
      }, 
      "alias": "B133243153928547", 
      "aliasType": "Default", 
      "card": { 
       "expiryMonth": "8", 
       "expiryYear": "2018", 
       "holderName": "Steve HAll", 
       "number": "0008" 
      }, 
      "contractTypes": [ 
       "RECURRING" 
      ], 
      "creationDate": "2017-01-26T23:11:20+01:00", 
      "firstPspReference": "8524854686798738", 
      "paymentMethodVariant": "visadebit", 
      "recurringDetailReference": "8414854686802111", 
      "variant": "visa" 
     } 
], 
"invalidOneclickContracts": "false", 
"lastKnownShopperEmail": "[email protected]", 
"shopperReference": "xggZcGauSSG5jP+akIlijQ==" 
} 

Для имени объекта может быть, вы можете попробовать что-то вроде

public class RecurringDetailsResult 
    implements java.io.Serializable { 
private static final long serialVersionUID = 5297684963950973136L; 
private Date creationDate; 
private String shopperReference; 
private List<Map<String,RecurringDetail>> details; 
private String lastKnownShopperEmail; 

@JsonGetter("creationDate") 
public Date getCreationDate () { 
    return this.creationDate; 
} 

@JsonSetter("creationDate") 
public void setCreationDate (Date value) { 
    this.creationDate = value; 
} 

@JsonGetter("shopperReference") 
public String getShopperReference () { 
    return this.shopperReference; 
} 

@JsonSetter("shopperReference") 
public void setShopperReference (String value) { 
    this.shopperReference = value; 
} 

@JsonGetter("details") 
public List<Map<String, RecurringDetail>> getDetails () { 
    return this.details; 
} 

@JsonSetter("details") 
public void setDetails (List<Map<String, RecurringDetail>> value) { 
    this.details = value; 
} 

@JsonGetter("lastKnownShopperEmail") 
public String getLastKnownShopperEmail () { 
    return this.lastKnownShopperEmail; 
} 

@JsonSetter("lastKnownShopperEmail") 
public void setLastKnownShopperEmail (String value) { 
    this.lastKnownShopperEmail = value; 
} 

} 
Смежные вопросы