Нам нужно реализовать собственный десериализатор.Поскольку мы хотим пропустить одно внутреннее поле, наша реализация должна:
{
- пропустить начальный объект "any_field_name"
- пропустить любое имя поля.Мы предполагаем, что у нас есть только одно внутреннее поле. [{}, ..., {}]
- использовать десериализатор по умолчанию для List
. }
- пропустить конечный объект
Использование вышеуказанной концепции должно быть простым:
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'}]}
Для получения дополнительной информации читайте:
- CustomДесериализатор Джексона Получение доступа к текущему классу поля
- Начало работы с пользовательской десериализацией в Джексоне
- Исключения Джексона - проблемы и решения
- Джексон UNWRAP_ROOT_VALUE
- Конфигурирование ObjectMapper весной