使用 Jackson 反序列化数组 JSON 时出错

Error while deserializing array JSON with Jackson

希望有人能提供帮助。我正在尝试反序列化从 Prestashop 1.7 的 Web 服务获取的 class Product 的 JSON 数组,使用 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"
    }
]

}

class Products 只是 class 的 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;
    }
}

而 class 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
}

还有更多字段,但我省略了,因为这并不重要。

我知道如何反序列化 class Product 但如何从 JSON 中获取 List<Product>? 我正在使用 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.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.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=15=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.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;

我想你可能理解这一点,但在基本层面上,你做错了。

class 中的字段名称必须与 JSON 中的字段名称完全匹配,或者您必须使用 @JsonProperty 注释来标识中的确切字段名称JSON。 这是一个示例,显示如何将 JSON 中的 new 字段映射到您的对象:

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

注意 @JsonProperty 注释中的名称与 JSON 中的字段名称完全匹配。 只要那是真的, JAVA 字段的实际名称无关紧要。 这也适用于 "new" 字段:

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.

Jackson 错误消息表明存在无法识别的 JSON 中名为 "delivery_in_stock" 的字段。

添加一个字段以包含 JSON 中的 "delivery_in_stock" 字段值,或者使用此注释指示 Jackson 忽略未映射的属性:

@JsonIgnoreProperties(ignoreUnknown = true)

如果您的输入 JSON 有额外字段,您可以使用以下任何方法允许反序列化:

  1. 您可以将整个 ObjectMapper 配置为不会在额外字段上失败:

    ObjectMapper 映射器 = new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    Products products = mapper.readValue(url, Products.class);
    
  2. 使用@JsonIgnoreProperties(ignoreUnknown = true)

  3. 注释您的产品class