2

I have a maven project using Spring Boot 2.1.9 and RestTemplate, when I use RestTemplate.exchange method it shows "Cannot deserialize instance of 'java.lang.Long' at runtime because of xml tag with 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>
cviniciusm
  • 139
  • 1
  • 2
  • 13

2 Answers2

2

I solved this issue including the jackson-dataformat-xml, jackson-core and jackson-databind version 2.10.0 dependencies on pom.xml .

cviniciusm
  • 139
  • 1
  • 2
  • 13
1

You can register your own DeserializationProblemHandler and return null when <value xsi:nil="true" /> appears:

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);
    }
}

Above code prints:

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

See also:

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146