【问题标题】:Custom retrofit converter定制改造转换器
【发布时间】:2017-03-23 15:38:26
【问题描述】:

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

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

如果可能,我如何让 Retrofit 在 xml 标记之后开始解析对象,如果没有,是否有其他解决方案?

【问题讨论】:

    标签: android json xml gson


    【解决方案1】:

    这很容易。据我所知,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();
    

    【讨论】:

    • 你知道如何在 responseBody 中写一些东西吗?
    【解决方案2】:

    您必须编写您的自定义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(...);
    

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

    【讨论】:

    • @Jesus Dimrix,现在你明白了。可以自己实现的解析逻辑。
    猜你喜欢
    • 2015-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-20
    • 2017-08-12
    • 2015-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多