Преобразуйте объект Java с помощью org.w3c.dom.Element в строку и получите ошибку при обратном преобразовании - PullRequest
1 голос
/ 18 марта 2019

У меня есть класс оболочки:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Wrapper {
    private String id;
    private int number;
    private Element internal;
}

У меня есть внутренний класс:

@XmlRootElement
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment {
    private BigDecimal amount;
    private String account;
}

Я создаю Payment, преобразую его в org.w3c.dom.Element и задаю Wrapper. И после этого я конвертирую Wrapper в строку , использую Json Jackson

И после этого я пытаюсь преобразовать другой путь - Строка в Объект И получаю ошибку.

public class Main {
    public static void main(String[] args) throws JAXBException, ParserConfigurationException, IOException {

        ObjectMapper mapper = new ObjectMapper();

        Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        JAXBContext context = JAXBContext.newInstance(Payment.class);
        Marshaller marshaller = context.createMarshaller();

        //create paymant
        Payment payment = new Payment(BigDecimal.valueOf(100), "666");

        //convert to Element
        marshaller.marshal(payment, document);
        Element element = document.getDocumentElement();

        //set Paymant as Element to Wrapper
        Wrapper wrapper = new Wrapper("123321", 987, element);

        //convert Wrapper to string
        String wrapperAsString = mapper.writeValueAsString(wrapper);

        System.out.println(wrapperAsString);

        //convert the other way
        Wrapper restoreWrapper = mapper.readValue(wrapperAsString, Wrapper.class);

    }
}

Когда я конвертирую Wrapper в String, я получаю такой результат:

{
    "id": "123321",
    "number": 987,
    "internal": "<?xml version=\"1.0\" encoding=\"UTF-16\"?>\n<payment><account>666</account><amount>100</amount></payment>"
}

Но при конвертации другим способом я получаю исключение:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Problem deserializing property 'internal' (expected type: [simple type, class org.w3c.dom.Element]; actual type: `com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl`), problem: argument type mismatch
 at [Source: (String)"{"id":"123321","number":987,"internal":"<?xml version=\"1.0\" encoding=\"UTF-16\"?>\n<payment><account>666</account><amount>100</amount></payment>"}"; line: 1, column: 40] (through reference chain: com.pavel.Wrapper["internal"])
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:278)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:597)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:141)
    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:3004)
    at com.pavel.Main.main(Main.java:36)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
    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 com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:139)

1 Ответ

1 голос
/ 18 марта 2019

У вас есть два варианта:

  1. Изменить тип internal на Document или Node.
  2. Напишите пользовательский десериализатор, который будет делать то же, что и вы, в строке: Element element = document.getDocumentElement();

Пользовательский десериализатор:

class ElementDeserializer extends DOMDeserializer<Element> {

    private static final long serialVersionUID = 1L;

    public ElementDeserializer() {
        super(Element.class);
    }

    @Override
    public Element _deserialize(String value, DeserializationContext ctxt)
        throws IllegalArgumentException {
        return parse(value).getDocumentElement();
    }
}

Вы можете зарегистрировать его, как показано ниже:

SimpleModule elementModule = new SimpleModule();
elementModule.addDeserializer(Element.class, new ElementDeserializer());

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(elementModule);

Но я предлагаю остаться с нестандартными десериализаторами для Documen - com.fasterxml.jackson.databind.ext.DOMDeserializer.DocumentDeserializer и Node - com.fasterxml.jackson.databind.ext.DOMDeserializer.NodeDeserializer.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...