Skip to content

Instantly share code, notes, and snippets.

@andersonkxiass
Last active September 7, 2023 14:31
Show Gist options
  • Save andersonkxiass/bb86f0cd0910f243656d457a0ca45ec7 to your computer and use it in GitHub Desktop.
Save andersonkxiass/bb86f0cd0910f243656d457a0ca45ec7 to your computer and use it in GitHub Desktop.
Retrofit 2 Custom Xml Converter using Xstream library

#How to use

Build.gradle

dependencies {

  	//Add Retrofit dependencies 
  
	compile ('com.thoughtworks.xstream:xstream:1.4.7') {
	        exclude group: 'xmlpull', module: 'xmlpull'
	}
}

XStreamXmlConverterFactory

import com.thoughtworks.xstream.XStream;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;

/**
 * Created by Anderson on 02/08/2016.
 *
 */
public class XStreamXmlConverterFactory extends Converter.Factory {

    /** Create an instance using a default {@link com.thoughtworks.xstream.XStream} instance for conversion. */
    public static XStreamXmlConverterFactory create() {
        return create(new XStream());
    }

    /** Create an instance using {@code xStream} for conversion. */
    public static XStreamXmlConverterFactory create(XStream xStream) {
        return new XStreamXmlConverterFactory(xStream);
    }

    private final XStream xStream;

    private XStreamXmlConverterFactory(XStream xStream) {
        if (xStream == null) throw new NullPointerException("xStream == null");
        this.xStream = xStream;
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {

        if (!(type instanceof Class)) {
            return null;
        }

        Class<?> cls = (Class<?>) type;

        return new XStreamXmlResponseBodyConverter<>(cls, xStream);
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {

        if (!(type instanceof Class)) {
            return null;
        }

        return new XStreamXmlRequestBodyConverter<>(xStream);
    }
}

XStreamXmlRequestBodyConverter

import com.thoughtworks.xstream.XStream;

import java.io.IOException;
import java.io.OutputStreamWriter;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import retrofit2.Converter;

/**
 * Created by Anderson on 02/08/2016.
 *
 */
final class XStreamXmlRequestBodyConverter<T> implements Converter<T, RequestBody> {

    private static final MediaType MEDIA_TYPE = MediaType.parse("application/xml; charset=UTF-8");
    private static final String CHARSET = "UTF-8";

    private final XStream xStream;

    XStreamXmlRequestBodyConverter(XStream xStream) {
        this.xStream = xStream;
    }

    @Override
    public RequestBody convert(T value) throws IOException {

        Buffer buffer = new Buffer();

        try {
            OutputStreamWriter osw = new OutputStreamWriter(buffer.outputStream(), CHARSET);
            xStream.toXML(value, osw);
            osw.flush();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
    }
}

XStreamXmlResponseBodyConverter

import com.thoughtworks.xstream.XStream;

import java.io.IOException;

import okhttp3.ResponseBody;
import retrofit2.Converter;

/**
 * Created by Anderson on 02/08/2016.
 *
 */
final class XStreamXmlResponseBodyConverter <T> implements Converter<ResponseBody, T> {

    private final Class<T> cls;
    private final XStream xStream;

    XStreamXmlResponseBodyConverter(Class<T> cls, XStream xStream) {
        this.cls = cls;
        this.xStream = xStream;
    }

    @Override
    public T convert(ResponseBody value) throws IOException {

        try {

            this.xStream.processAnnotations(cls);
            Object object =  this.xStream.fromXML(value.byteStream());
            return (T) object;

        }finally {
            value.close();
        }
    }
}

Sample

 Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("")
        .addConverterFactory(XStreamXmlConverterFactory.create(new XStream(new DomDriver())))
        .client(client)
        .build();
@phpgodnulled
Copy link

phpgodnulled commented Sep 25, 2017

Hi Anderson,

I have a question about your converter. At this moment i'm using Simple xml to convert Retrofit classes to xml documents. The only problem with Simple is that it can't handle self-closing xml tags. Now I was doing some research on alternatives for Simple and I found your comment here: https://futurestud.io/tutorials/retrofit-replace-the-integrated-json-converter . My question is: can i handle self-closing xml tags with your converter? I'm hoping for a quick response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment