Как десериализовать Java Long, у которого тег xml имеет xsi: nil? - PullRequest
2 голосов
/ 07 октября 2019

У меня есть проект maven, использующий Spring Boot 2.1.9 и RestTemplate, когда я использую метод RestTemplate.exchange, он показывает «Невозможно десериализовать экземпляр java.lang.Long» во время выполнения из-за тега xml с xsi: nil = »true ".

class Pojo {
    private List<Long> values;
}

xml:

<?xml version="1.0" encoding="utf-8"?>
<PojoResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/">
    <values>
        <value>10</value>
        <value xsi:nil="true" />
        <value>20</value>
    </values>
</PojoResponse>

Ответы [ 2 ]

0 голосов
/ 09 октября 2019

Я решил эту проблему, включая зависимости jackson-dataformat-xml, jackson-core и jackson-databind версии 2.10.0 от pom.xml.

0 голосов
/ 08 октября 2019

Вы можете зарегистрировать свой собственный DeserializationProblemHandler и вернуть null, когда появится <value xsi:nil="true" />:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

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

public class XmlMapperApp {

    public static void main(String[] args) throws Exception {
        File xmlFile = new File("./resource/test.xml").getAbsoluteFile();

        XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.setConfig(xmlMapper.getDeserializationConfig().withHandler(new NullableItemsDeserializationProblemHandler()));
        System.out.println(xmlMapper.readValue(xmlFile, Pojo.class));
    }
}

class NullableItemsDeserializationProblemHandler extends DeserializationProblemHandler {
    @Override
    public Object handleUnexpectedToken(DeserializationContext ctxt, Class<?> targetType, JsonToken t, JsonParser p, String failureMsg) throws IOException {
        if (targetType == Long.class && p.currentToken() == JsonToken.START_OBJECT) {
            boolean isNull = false;
            while (p.currentToken() != JsonToken.END_OBJECT) {
                p.nextToken();
                switch (p.currentToken()) {
                    case FIELD_NAME:
                        if ("nil".equals(p.getText())) {
                            isNull = true;
                        }
                }
            }
            if (isNull) {
                return null;
            }
        }
        return super.handleUnexpectedToken(ctxt, targetType, t, p, failureMsg);
    }
}

Над кодом напечатано:

Pojo{values=[10, null, 20]}

См. Также:

...