Search code examples
javaandroidxml-parsingretrofit2simple-xml-converter

Simple XML Serialization with Retrofit2 with Multiple In-Line Items


Using Retrofit2 with SimpleXmlConverterFactory

My issue is multiple in-line (I believe?) Errors in the error response's errorBody.

I have been referring to this link from Simple XML Serialization as my source of information.

I am working with the below response:

<?xml version="1.0" encoding="utf-8"?>
<Errors>
    <Error>
        <Code>1</Code>
        <Info>This is why</Info>
    </Error>
    <Error>
        <Code>2</Code>
        <Info>This is why</Info>
    </Error>
</Errors>

My current java objects are ErrorResponse.java:

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

import java.util.List;

@Root(name="Errors")
public class ErrorResponse {

    @ElementList(name="Error", inline = true)
    List<Error> errors;

    public ErrorResponse() {
        // no arg constructor
    }

    public void setErrors(List<Error> errors) {
        this.errors = errors;
    }

    public List<Error> getErrors() {
        return this.errors;
    }
}

and Error.java:

import org.simpleframework.xml.Element;

public class Error {

    @Element(name="Code")
    int code;

    @Element(name="Info")
    String info;

    public Error() {
        // no arg constructor
    }

    public void setCode(int code) {
        this.code = code;
    }

    public int getCode() {
        return this.code;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public String getInfo() {
        return this.info;
    }
}

The error I get when trying to parse the errorBody of the response is:

java.lang.RuntimeException:
org.simpleframework.xml.core.ElementException: 
Element 'Error' does not have a match in class com.my.package.ErrorResponse at line 1

If there's only 1 error item and I change the ErrorResponse class to:

..
@Root
public class ErrorResponse {

    @Element(name="Error")
    Error error;
...
...

Then everything works fine and dandy. The issue comes when there are multiple Errors. Any help or suggestions getting this XML to be parsed properly would be great. I use the below code for the errorBody parsing of the response:

Converter<ResponseBody, ErrorResponse> converter = mRetrofit.responseBodyConverter(ErrorResponse.class, new Annotation[0]);
try {
    ErrorResponse errorResponse = converter.convert(response.errorBody());
} catch (IOException e) {
    e.printStackTrace();
}

Solution

    • The closing info,</Info>, tag needs to be capitalized in your sample XML
    • ErrorResponse needs a name of Errors to match the XML
    • @ElementList doesn't need the name specified when it's inline
    • ErrorItem needs @Root(name = "Error")

    Here is the code for ErrorResponse:

    @Root(name = "Errors")
    public class ErrorResponse {
    
        @ElementList(inline = true)
        List<Error> errors;
    
        public ErrorResponse() {
            // no arg constructor
        }
    
        public void setErrors(List<Error> errors) {
            this.errors = errors;
        }
    
        public List<Error> getErrors() {
            return this.errors;
        }
    }
    

    For Error:

    @Root(name = "Error")
    public class Error {
    
        @Element(name = "Code")
        int code;
    
        @Element(name = "Info")
        String info;
    
        public Error() {
            // no arg constructor
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    
        public int getCode() {
            return this.code;
        }
    
        public void setInfo(String info) {
            this.info = info;
        }
    
        public String getInfo() {
            return this.info;
        }
    }
    

    Fixed sample XML:

    <?xml version="1.0" encoding="utf-8"?>
    <Errors>
        <Error>
            <Code>1</Code>
            <Info>This is why</Info>
        </Error>
        <Error>
            <Code>2</Code>
            <Info>This is why</Info>
        </Error>
    </Errors>