Ошибка при десериализации массива JSON с Джексоном - PullRequest
0 голосов
/ 25 января 2019

надеюсь, кто-то может помочь.Я пытаюсь десериализовать массив JSON класса Product, полученный из веб-сервиса Prestashop 1.7, используя URL-адрес, подобный этому http://myshop.com/api/products/?display=full&filter[reference]=[0003]&output_format=JSON.Вывод JSON выглядит так:

{
"products": [{
        "id": 1,
        "id_manufacturer": "0",
        "id_supplier": "0",
        "id_category_default": "2",
        "new": null,
        "cache_default_attribute": "0",
        "id_default_image": "",
        "id_default_combination": 0,
        "id_tax_rules_group": "3",
        "position_in_category": "0",
        "manufacturer_name": false,
        "quantity": "0"
    },
    {
        "id": 2,
        "id_manufacturer": "0",
        "id_supplier": "0",
        "id_category_default": "2",
        "new": null,
        "cache_default_attribute": "0",
        "id_default_image": "",
        "id_default_combination": 0,
        "id_tax_rules_group": "3",
        "position_in_category": "0",
        "manufacturer_name": false,
        "quantity": "0"
    }
]

}

Класс Products представляет собой просто List класса Product, определяемого так:

public class Products  {

    private List <Product> products;

    public Products() {
        super();
    }

    public List<Product> getProducts(){
        return this.products;
    }
    public void setProducts(List<Product> products){
        this.products = products;
    }
}

И класс Product вот так:

public class Product(){
    @JsonProperty("id")
    private long id;

    @JsonProperty("id_manufacturer")
    private long idManufacturer;

    @JsonProperty("id_supplier")
    private long idSupplier;

    @JsonProperty("id_category_default")
    private long idCategoryDefault;

    @JsonProperty("new")
    private String _new;

    @JsonProperty("cache_default_attribute")
    private long cacheDefaultAttribute;

    @JsonProperty("id_default_image")
    private long idDefaultImage;

    @JsonProperty("id_default_combination")
    private long idDefaultCombination;

    @JsonProperty("id_tax_rules_group")
    private long idTaxRulesGroup;

    @JsonProperty("position_in_category")
    private long positionInCategory;

    @JsonProperty("manufacturer_name")
    private String manufacturerName;

    @JsonProperty("quantity")
    private long quantity;

    //getters and setters
}

Есть еще поля, но я опускаю их тогда, потому что это не имеет значения.

Я знаю, как десериализовать класс Product но как я могу получить List<Product> от JSON?Я пользуюсь jackson-databind-2.9.8.jar.

Заранее спасибо и хороших выходных.Отредактировано: Когда я пытаюсь сделать это:

   SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
    ObjectMapper mapper = new ObjectMapper();
    mapper.setDateFormat(df);
    URL url = new URL("http://myshop.com/api/products/?display=full&filter[reference]=[0003]&output_format=JSON");
    Products products = mapper.readValue(url, Products.class);

я получаю эту ошибку

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "delivery_in_stock" (class com.fnieves.precios.pshop4j.pojos.entities.Product), not marked as ignorable (58 known properties: "active", "show_price", "low_stock_alert", "advanced_stock_management", "quantity", "date_add", "state", "visibility", "uploadable_files", "low_stock_threshold", "supplier_reference", "id", "id_shop_default", "new", "cache_default_attribute", "id_category_default", "additional_shipping_cost", "height", "upc", "pack_stock_type", "id_default_combination", "location", "id_default_image", "type", "customizable", "redirect_type", "position_in_category", "depth", "width", "wholesale_price", "price", "reference", "cache_has_attachments", "cache_is_pack", "additional_delivery_times", "show_condition", "unit_price_ratio", "available_for_order", "available_date", "minimal_quantity", "id_supplier", "indexed", "ean13", "id_manufacturer", "isbn", "weight", "ecotax", "id_type_redirected", "id_tax_rules_group", "text_fields", "online_only", "condition", "on_sale", "manufacturer_name", "quantity_discount", "is_virtual", "unity", "date_upd"])
at [Source: (URL); line: 1, column: 628] (through reference chain: com.fnieves.precios.pshop4j.pojos.list.Products["products"]->java.util.ArrayList[0]->com.fnieves.precios.pshop4j.pojos.entities.Product["delivery_in_stock"])

at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:823)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1153)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1589)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1567)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:294)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:286)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2959)
at TestJson.readArray(TestJson.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Даже когда все поля помечены @JsonProperty или @JsonIgnore, как это

@JsonIgnore
private LanguageElements deliveryInStock;

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Вы можете использовать любой из приведенных ниже подходов, чтобы разрешить десериализацию, если ваш входной JSON имеет дополнительные поля:

  1. Вы можете настроить весь ObjectMapper так, чтобы он не завершался с ошибкой на дополнительных полях:

    ObjectMapper mapper = new ObjectMapper () .configure (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    Products products = mapper.readValue(url, Products.class);
    
  2. Аннотируйте свой класс Product с помощью @JsonIgnoreProperties (ignoreUnknown = true)

0 голосов
/ 25 января 2019

Я думаю, вы понимаете это, но на базовом уровне вы делаете это неправильно.

Имя полей в классе должно точно соответствовать именам полей в JSON, или вы должны использовать аннотацию @JsonProperty для определения точного имени поля в JSON. Вот пример, показывающий, как сопоставить поле new из JSON с вашим объектом:

public class Product
{
  @JsonProperty("new")
  private String _new;
}

Обратите внимание, что имя в аннотации @JsonProperty точно совпадает с именем поля в JSON. Пока это верно, фактическое имя поля JAVA не имеет значения. Это также будет работать для «нового» поля:

public class Product
{
  @JsonProperty("new")
  private String thisFieldNameDoesNotMatter;
}

Редактировать: добавлены дополнительные сведения, отражающие изменение вопроса.

Ответ на вашу проблему таков: обратите внимание.

На самом деле прочитайте ошибку, которую дал вам Джексон:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: 
Unrecognized field "delivery_in_stock"
... additional details included by Jackson, but deleted here.

Сообщение об ошибке Джексона указывает на наличие нераспознанного поле в JSON с именем «delivery_in_stock».

Либо добавьте поле, содержащее значение поля «delivery_in_stock» из JSON, либо дайте команду Джексону игнорировать несопоставленные свойства, используя эту аннотацию:

@JsonIgnoreProperties(ignoreUnknown = true)
...