Skully1
Skully1

Reputation: 33

Cannot construct instance. Deserializing Xml in Java (Spring Boot)

Hello I have issue while deserializing Xml output into desriable object. I get com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of com.example.demo.models.responses.FxRate (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('EU'). I tried to use JacksonXml or JsonPropery annotations but no avail.

Controller

package com.example.demo.controllers;

import com.example.demo.models.responses.FxRates;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

@RestController
public class TestController {
    @GetMapping("/currency")
    public FxRates GetCurrency() throws IOException, InterruptedException {
        HttpRequest request =  HttpRequest.newBuilder()
                .uri(URI.create("http://www.lb.lt/webservices/FxRates/FxRates.asmx/getFxRates?tp=eu&dt=2017-12-25"))
                .header("Content-Type", "text/xml")
                .GET()
                .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
                .send(request, HttpResponse.BodyHandlers.ofString());


        var test = response.body();

        XmlMapper xmlMapper = new XmlMapper();
        FxRates value = xmlMapper.readValue(response.body(), FxRates.class);

        return value;
    }
}

Deserialized classes

package com.example.demo.models.responses;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;


import java.util.ArrayList;
import java.util.List;

@JsonPropertyOrder({"FxRate", "xlmns"})
public class FxRates {
    //@JacksonXmlProperty(localName = "FxRate")
    @JsonProperty("FxRate")
    public ArrayList<com.example.demo.models.responses.FxRate> FxRate;
    @JsonProperty("xlmns")
    public String xmlns;
    
        public FxRates()
    {

    }
    public FxRates(ArrayList<com.example.demo.models.responses.FxRate> fxRate, String xmlns)  {
        FxRate = fxRate;
        this.xmlns = xmlns;
        //this.text = text;
    }

    public ArrayList<com.example.demo.models.responses.FxRate> getFxRate() {
        return FxRate;
    }

    public void setFxRate(ArrayList<com.example.demo.models.responses.FxRate> fxRate) {
        FxRate = fxRate;
    }

    public String getXmlns() {
        return xmlns;
    }

    public void setXmlns(String xmlns) {
        this.xmlns = xmlns;
    }
}

package com.example.demo.models.responses;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;

public class FxRate {
    @JsonProperty("Tp")
    public String Tp;
    public String Dt;
    public List<CcyAmt> CcyAmt;

      public String getTp() {
        return Tp;
    }

    public void setTp(String tp) {
        Tp = tp;
    }

    public String getDt() {
        return Dt;
    }

    public void setDt(String dt) {
        Dt = dt;
    }

    public List<com.example.demo.models.responses.CcyAmt> getCcyAmt() {
        return CcyAmt;
    }

    public void setCcyAmt(List<com.example.demo.models.responses.CcyAmt> ccyAmt) {
        CcyAmt = ccyAmt;
    }

    public FxRate()
    {

    }
    public FxRate(String tp, String dt, List<com.example.demo.models.responses.CcyAmt> ccyAmt) {
        Tp = tp;
        Dt = dt;
        CcyAmt = ccyAmt;
    }
}

package com.example.demo.models.responses;

public class CcyAmt {
    public String Ccy;
    public String Amt;

     public String getCcy() {
        return Ccy;
    }

    public void setCcy(String ccy) {
        Ccy = ccy;
    }

    public String getAmt() {
        return Amt;
    }

    public void setAmt(String amt) {
        Amt = amt;
    }

    public CcyAmt()
    {

    }
    public CcyAmt(String ccy, String amt) {
        Ccy = ccy;
        Amt = amt;
    }

Example Response

<?xml version="1.0" encoding="utf-8"?>
<FxRates xmlns="http://www.lb.lt/WebServices/FxRates">
  <FxRate>
    <Tp>EU</Tp>
    <Dt>2017-12-22</Dt>
    <CcyAmt>
      <Ccy>EUR</Ccy>
      <Amt>1</Amt>
    </CcyAmt>
    <CcyAmt>
      <Ccy>AUD</Ccy>
      <Amt>1.5358</Amt>
    </CcyAmt>
  </FxRate>
</FxRates>

Upvotes: 1

Views: 478

Answers (1)

You're just missing an @JacksonXmlElementWrapper(useWrapping = false) to on both the ArrayList<FxRate> and List<CcyAmt> or wrap it in an additional XML element.

The other annotations are also not required for it to work as expected.

Upvotes: 3

Related Questions