gpt4 book ai didi

java - Jackson - 将内部对象列表反序列化为更高级别的列表

转载 作者:行者123 更新时间:2023-11-30 06:41:54 25 4
gpt4 key购买 nike

使用 Spring Boot 和 Jackson,如何将包装/内部列表反序列化为直接在外部级别的列表?

例如,我有:

{
"transaction": {
"items": {
"item": [
{
"itemNumber": "193487654",
"itemDescription": "Widget",
"itemPrice": "599.00",
"itemQuantity": "1",
"itemBrandName": "ACME",
"itemCategory": "Electronics",
"itemTax": "12.95"
},
{
"itemNumber": "193487654",
"itemDescription": "Widget",
"itemPrice": "599.00",
"itemQuantity": "1",
"itemBrandName": "ACME",
"itemCategory": "Electronics",
"itemTax": "12.95"
}
]
},
...
}
}

在JSON中,itemitems下的一个列表;但我想将它解析为一个名为 items 的列表,直接在 transaction 下,而不是定义一个包含名为 的列表的 DTO Items >项目

这可能吗?如何定义这个 DTO Item

public class TrasactionDTO {
private List<Item> items;
...
}

public class Item {

}

这个问题类似但是没有解决问题。 Deserialize wrapped list using Jackson

最佳答案

我们需要实现自定义反序列化器。因为我们想跳过一个内部字段,所以我们的实现应该:

  1. { - 跳过起始对象
  2. "any_field_name" - 跳过任何字段名称。我们假设我们只有一个内场。
  3. [{}, ..., {}] - 为 List 使用默认反序列化器。
  4. } - 跳过结束对象

使用上面的概念实现应该很容易:

public class InnerListDeserializer extends JsonDeserializer<List> implements ContextualDeserializer {

private final JavaType propertyType;

public InnerListDeserializer() {
this(null);
}

public InnerListDeserializer(JavaType propertyType) {
this.propertyType = propertyType;
}

@Override
public List deserialize(JsonParser p, DeserializationContext context) throws IOException {
p.nextToken(); // SKIP START_OBJECT
p.nextToken(); // SKIP any FIELD_NAME

List list = context.readValue(p, propertyType);

p.nextToken(); // SKIP END_OBJECT

return list;
}

@Override
public JsonDeserializer<?> createContextual(DeserializationContext context, BeanProperty property) {
return new InnerListDeserializer(property.getType());
}
}

假设我们有这样的 JSON 有效载荷:

{
"transaction": {
"items": {
"item": [
{
"itemNumber": "193487654",
"itemDescription": "Widget",
"itemPrice": "599.00",
"itemQuantity": "1",
"itemBrandName": "ACME",
"itemCategory": "Electronics",
"itemTax": "12.95"
},
{
"itemNumber": "193487654",
"itemDescription": "Widget",
"itemPrice": "599.00",
"itemQuantity": "1",
"itemBrandName": "ACME",
"itemCategory": "Electronics",
"itemTax": "12.95"
}
]
},
"name": "Pickle Rick"
}
}

JSON 之上我们可以映射到下面的 POJO 类:

@JsonRootName("transaction")
public class Transaction {

private String name;
private List<Item> items;

@JsonDeserialize(using = InnerListDeserializer.class)
public List<Item> getItems() {
return items;
}

// getters, setters, toString
}

public class Item {

private String itemNumber;

// getters, setters, toString
}

为了展示它适用于许多不同的模型,让我们再介绍一个 JSON 负载:

{
"product": {
"products": {
"innerArray": [
{
"id": "1234"
}
]
}
}
}

还有两个 POJO 类:

@JsonRootName("product")
class Product {

private List<ProductItem> products;

@JsonDeserialize(using = InnerListDeserializer.class)
public List<ProductItem> getProducts() {
return products;
}

// getters, setters, toString
}

class ProductItem {

private String id;

// getters, setters, toString
}

现在我们可以测试我们的解决方案了:

import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class JSoupTest {

public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

File jsonFile = new File("Path to 1-st JSON").getAbsoluteFile();
File jsonFile1 = new File("Path to 2-nd JSON").getAbsoluteFile();

System.out.println(mapper.readValue(jsonFile, Transaction.class));
System.out.println(mapper.readValue(jsonFile1, Product.class));
}
}

上面的例子打印:

Transaction{items=[Item{itemNumber=193487654}, Item{itemNumber=193487654}], name='Pickle Rick'}
Product{products=[ProductItem{id='1234'}]}

更多信息请阅读:

  1. Custom Jackson Deserializer Getting Access to Current Field Class
  2. Getting Started with Custom Deserialization in Jackson
  3. Jackson Exceptions – Problems and Solutions
  4. Jackson UNWRAP_ROOT_VALUE
  5. Configuring ObjectMapper in Spring

关于java - Jackson - 将内部对象列表反序列化为更高级别的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54424576/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com