定制改造转换器

时间:2017-03-23 15:38:26

标签: android json xml gson

我使用Retrofit作为REST客户端并获得以下响应:

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">{"Response":{"Status":"success","Response........... </string>

如果可能的话,我如何让Retrofit开始在xml标签之后解析对象,如果没有,还有其他解决方案吗?

2 个答案:

答案 0 :(得分:2)

这很简单。据我所知,Retrofit不提供转换器链,但你仍然可以包装多个转换器:

final class XmlWrappedConverterFactory
        extends Converter.Factory {

    // This is the converter factory the deserialization will be delegated to   
    private final Converter.Factory backingConverterFactory;

    private XmlWrappedConverterFactory(final Converter.Factory backingConverterFactory) {
        this.backingConverterFactory = backingConverterFactory;
    }

    static Converter.Factory create(final Converter.Factory backingConverterFactory) {
        return new XmlWrappedConverterFactory(backingConverterFactory);
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(final Type type, final Annotation[] annotations, final Retrofit retrofit) {
        final Converter<ResponseBody, ?> responseBodyConverter = backingConverterFactory.responseBodyConverter(type, annotations, retrofit);
        return new XmlWrappedResponseBodyConverter(responseBodyConverter);
    }

    private static final class XmlWrappedResponseBodyConverter
            implements Converter<ResponseBody, Object> {

        private final Converter<ResponseBody, ?> responseBodyConverter;

        private XmlWrappedResponseBodyConverter(final Converter<ResponseBody, ?> responseBodyConverter) {
            this.responseBodyConverter = responseBodyConverter;
        }

        @Override
        public Object convert(final ResponseBody responseBody)
                throws IOException {
            // Note the response is not converted to string in order to save memory and work in streaming fashion
            // So just fast-forward until '>' is found -- let's pretend it's an XML pretty much then
            fastForward(responseBody.charStream(), '>');
            // GsonConverterFactory uses charStream() as well, at this step the stream will be "fast-forwarded"
            return responseBodyConverter.convert(responseBody);
            // However, the GsonConverterFactory closes the charStream() so wer're unable to read it until the end -- not that bad in fact
        }

        private static void fastForward(final Reader reader, final char ch)
                throws IOException {
            // Just read until the given character is found or EOF
            int read;
            while ( (read = reader.read()) != ch && read != -1 ) {
            }
        }

    }

}

然后构建Retrofit实例很简单:

final Retrofit retrofit = new Builder()
        ...
        .addConverterFactory(XmlWrappedConverterFactory.create(GsonConverterFactory.create()))
        .build();

答案 1 :(得分:1)

您必须编写自定义Converter

这样的事情:

new Retrofit.Builder()
    .baseUrl(...)
    .addCallAdapterFactory(...)
    .addConverterFactory(new Converter.Factory() {
        @Override
        public Converter<ResponseBody, YourModel> responseBodyConverter(final Type type,
                                                                        final Annotation[] annotations, final Retrofit retrofit) {
            return new Converter<ResponseBody, YourModel>() {
                @Override
                public YourModel convert(final ResponseBody value) throws IOException {
                    String responseString = value.string();
                    int startIndex = responseString.indexOf(">");
                    ++startIndex;
                    int endIndex = responseString.indexOf("<", 1);
                    String jsonResponse = responseString.substring(startIndex, endIndex);
                    YourModel yourModel = new Gson().fromJson(jsonResponse, YourModel.class);
                    return yourModel;
                }
            };
        }
    })
    .build()
    .create(...);

注意,这只是一个草图,它可能无法正常运行,我还没有测试过。让我知道我是否应该编辑它。