android-cn/android-discuss

Retrofit GsonConverterFactory 解析带有转义符的数据

Opened this issue · 3 comments

KKaKa commented
  • 后台返回的数据:
{
    "code": "00",
    "mobileData": "[{\"publish_type\":\"00\",\"uv_value\":3,\"app_type\":\"02\",\"page_type\":\"\",\"customer_level\":\"ALL_CUSTOMER\",\"partner_level\":\"0\",\"rule_number\":0,\"click_number\":0,\"title\":\"超时\",\"create_operator\":\"zexin\",\"publish_operator\":\"wangchaocheng\",\"optimistic\":0,\"update_time\":\"2019-03-20 14:28:43\",\"pv_value\":10,\"publish_time\":\"2019-03-20 14:28:51\",\"link_url\":\"https://www.cnblogs.com/ailiailan/p/7388784.html\",\"id\":32,\"click_type\":\"H5\",\"create_time\":\"2019-02-26 09:36:33\",\"end_time\":\"2019-03-30 10:00:04\",\"link_title\":\"CNBLOGS\",\"message_type\":\"02\",\"optimistic_lastsync\":0,\"update_operator\":\"wangchaocheng\",\"start_time\":\"2019-02-25 09:36:01\",\"image_path\":\"http://.www.baidu.com\",\"popup_rule\":\"02\",\"region\":\"\",\"status\":\"NORMAL\"}]",
    "msg": "广告请求成功"
}
  • api代码:
    @POST(ACTION)
    @FormUrlEncoded
    Observable<ResponseBean<AdBaseBeanList>> getAds2(
            @Field("requestType") String requestType,
            @Field("encryptData") String encryptData,
            @Field("signature") String signature,
            @Field("validate") boolean validate
    );
  • retrofit代码:
            apiService.getAds2(Constant.PUSH_MESSAGE_HANDLE,encrypt,sign,true)
                    .map(new BaseFunc1<>())
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(observe); 
  • 问题:
I: │ com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 28 path $.mobileData
I: │ 	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:224)
I: │ 	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
I: │ 	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
I: │ 	at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
I: │ 	at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
I: │ 	at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:119)
I: │ 	at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:218)
I: │ 	at retrofit2.OkHttpCall.execute(OkHttpCall.java:180)
I: │ 	at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:41)
I: │ 	at io.reactivex.Observable.subscribe(Observable.java:10901)
I: │ 	at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
I: │ 	at io.reactivex.Observable.subscribe(Observable.java:10901)
I: │ 	at io.reactivex.internal.operators.observable.ObservableMap.subscribeActual(ObservableMap.java:33)
I: │ 	at io.reactivex.Observable.subscribe(Observable.java:10901)
I: │ 	at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
I: │ 	at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:452)
I: │ 	at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61)
I: │ 	at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52)
I: │ 	at java.util.concurrent.FutureTask.run(FutureTask.java:237)
I: │ 	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
I: │ 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
I: │ 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
I: │ 	at java.lang.Thread.run(Thread.java:762)
I: │ Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 28 path $.mobileData
I: │ 	at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385)
I: │ 	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:213)
I: │ 	... 22 more


  • 有人遇到这种吗,需要怎么解决好

比较笨的方法可以把 AdBaseBeanList 改成 String,数据接收到之后 用gson在转一下。

class mobileData{

    /**
     * publish_type : 00
     * uv_value : 3
     * app_type : 02
     * page_type :
     * customer_level : ALL_CUSTOMER
     * partner_level : 0
     * rule_number : 0
     * click_number : 0
     * title : 超时
     * create_operator : zexin
     * publish_operator : wangchaocheng
     * optimistic : 0
     * update_time : 2019-03-20 14:28:43
     * pv_value : 10
     * publish_time : 2019-03-20 14:28:51
     * link_url : https://www.cnblogs.com/ailiailan/p/7388784.html
     * id : 32
     * click_type : H5
     * create_time : 2019-02-26 09:36:33
     * end_time : 2019-03-30 10:00:04
     * link_title : CNBLOGS
     * message_type : 02
     * optimistic_lastsync : 0
     * update_operator : wangchaocheng
     * start_time : 2019-02-25 09:36:01
     * image_path : http://.www.baidu.com
     * popup_rule : 02
     * region :
     * status : NORMAL
     */

    private String publish_type;
    private int uv_value;
    private String app_type;
    private String page_type;
    private String customer_level;
    private String partner_level;
    private int rule_number;
    private int click_number;
    private String title;
    private String create_operator;
    private String publish_operator;
    private int optimistic;
    private String update_time;
    private int pv_value;
    private String publish_time;
    private String link_url;
    private int id;
    private String click_type;
    private String create_time;
    private String end_time;
    private String link_title;
    private String message_type;
    private int optimistic_lastsync;
    private String update_operator;
    private String start_time;
    private String image_path;
    private String popup_rule;
    private String region;
    private String status;

    public String getPublish_type() {
        return publish_type;
    }

    public void setPublish_type(String publish_type) {
        this.publish_type = publish_type;
    }

    public int getUv_value() {
        return uv_value;
    }

    public void setUv_value(int uv_value) {
        this.uv_value = uv_value;
    }

    public String getApp_type() {
        return app_type;
    }

    public void setApp_type(String app_type) {
        this.app_type = app_type;
    }

    public String getPage_type() {
        return page_type;
    }

    public void setPage_type(String page_type) {
        this.page_type = page_type;
    }

    public String getCustomer_level() {
        return customer_level;
    }

    public void setCustomer_level(String customer_level) {
        this.customer_level = customer_level;
    }

    public String getPartner_level() {
        return partner_level;
    }

    public void setPartner_level(String partner_level) {
        this.partner_level = partner_level;
    }

    public int getRule_number() {
        return rule_number;
    }

    public void setRule_number(int rule_number) {
        this.rule_number = rule_number;
    }

    public int getClick_number() {
        return click_number;
    }

    public void setClick_number(int click_number) {
        this.click_number = click_number;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getCreate_operator() {
        return create_operator;
    }

    public void setCreate_operator(String create_operator) {
        this.create_operator = create_operator;
    }

    public String getPublish_operator() {
        return publish_operator;
    }

    public void setPublish_operator(String publish_operator) {
        this.publish_operator = publish_operator;
    }

    public int getOptimistic() {
        return optimistic;
    }

    public void setOptimistic(int optimistic) {
        this.optimistic = optimistic;
    }

    public String getUpdate_time() {
        return update_time;
    }

    public void setUpdate_time(String update_time) {
        this.update_time = update_time;
    }

    public int getPv_value() {
        return pv_value;
    }

    public void setPv_value(int pv_value) {
        this.pv_value = pv_value;
    }

    public String getPublish_time() {
        return publish_time;
    }

    public void setPublish_time(String publish_time) {
        this.publish_time = publish_time;
    }

    public String getLink_url() {
        return link_url;
    }

    public void setLink_url(String link_url) {
        this.link_url = link_url;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getClick_type() {
        return click_type;
    }

    public void setClick_type(String click_type) {
        this.click_type = click_type;
    }

    public String getCreate_time() {
        return create_time;
    }

    public void setCreate_time(String create_time) {
        this.create_time = create_time;
    }

    public String getEnd_time() {
        return end_time;
    }

    public void setEnd_time(String end_time) {
        this.end_time = end_time;
    }

    public String getLink_title() {
        return link_title;
    }

    public void setLink_title(String link_title) {
        this.link_title = link_title;
    }

    public String getMessage_type() {
        return message_type;
    }

    public void setMessage_type(String message_type) {
        this.message_type = message_type;
    }

    public int getOptimistic_lastsync() {
        return optimistic_lastsync;
    }

    public void setOptimistic_lastsync(int optimistic_lastsync) {
        this.optimistic_lastsync = optimistic_lastsync;
    }

    public String getUpdate_operator() {
        return update_operator;
    }

    public void setUpdate_operator(String update_operator) {
        this.update_operator = update_operator;
    }

    public String getStart_time() {
        return start_time;
    }

    public void setStart_time(String start_time) {
        this.start_time = start_time;
    }

    public String getImage_path() {
        return image_path;
    }

    public void setImage_path(String image_path) {
        this.image_path = image_path;
    }

    public String getPopup_rule() {
        return popup_rule;
    }

    public void setPopup_rule(String popup_rule) {
        this.popup_rule = popup_rule;
    }

    public String getRegion() {
        return region;
    }

    public void setRegion(String region) {
        this.region = region;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

String json= "[{"publish_type":"00","uv_value":3,"app_type":"02","page_type":"","customer_level":"ALL_CUSTOMER","partner_level":"0","rule_number":0,"click_number":0,"title":"超时","create_operator":"zexin","publish_operator":"wangchaocheng","optimistic":0,"update_time":"2019-03-20 14:28:43","pv_value":10,"publish_time":"2019-03-20 14:28:51","link_url":"https://www.cnblogs.com/ailiailan/p/7388784.html","id":32,"click_type":"H5","create_time":"2019-02-26 09:36:33","end_time":"2019-03-30 10:00:04","link_title":"CNBLOGS","message_type":"02","optimistic_lastsync":0,"update_operator":"wangchaocheng","start_time":"2019-02-25 09:36:01","image_path":"http://.www.baidu.com","popup_rule":"02","region":"","status":"NORMAL"}]";

    List<mobileData> list = null;
    try {
        list = gson.fromJson(json, new TypeToken<List<mobileData>>(){}.getType());
    }catch (Exception e){
        e.printStackTrace();
    }`
KKaKa commented

比较笨的方法可以把 AdBaseBeanList 改成 String,数据接收到之后 用gson在转一下。

class mobileData{

    /**
     * publish_type : 00
     * uv_value : 3
     * app_type : 02
     * page_type :
     * customer_level : ALL_CUSTOMER
     * partner_level : 0
     * rule_number : 0
     * click_number : 0
     * title : 超时
     * create_operator : zexin
     * publish_operator : wangchaocheng
     * optimistic : 0
     * update_time : 2019-03-20 14:28:43
     * pv_value : 10
     * publish_time : 2019-03-20 14:28:51
     * link_url : https://www.cnblogs.com/ailiailan/p/7388784.html
     * id : 32
     * click_type : H5
     * create_time : 2019-02-26 09:36:33
     * end_time : 2019-03-30 10:00:04
     * link_title : CNBLOGS
     * message_type : 02
     * optimistic_lastsync : 0
     * update_operator : wangchaocheng
     * start_time : 2019-02-25 09:36:01
     * image_path : http://.www.baidu.com
     * popup_rule : 02
     * region :
     * status : NORMAL
     */

    private String publish_type;
    private int uv_value;
    private String app_type;
    private String page_type;
    private String customer_level;
    private String partner_level;
    private int rule_number;
    private int click_number;
    private String title;
    private String create_operator;
    private String publish_operator;
    private int optimistic;
    private String update_time;
    private int pv_value;
    private String publish_time;
    private String link_url;
    private int id;
    private String click_type;
    private String create_time;
    private String end_time;
    private String link_title;
    private String message_type;
    private int optimistic_lastsync;
    private String update_operator;
    private String start_time;
    private String image_path;
    private String popup_rule;
    private String region;
    private String status;

    public String getPublish_type() {
        return publish_type;
    }

    public void setPublish_type(String publish_type) {
        this.publish_type = publish_type;
    }

    public int getUv_value() {
        return uv_value;
    }

    public void setUv_value(int uv_value) {
        this.uv_value = uv_value;
    }

    public String getApp_type() {
        return app_type;
    }

    public void setApp_type(String app_type) {
        this.app_type = app_type;
    }

    public String getPage_type() {
        return page_type;
    }

    public void setPage_type(String page_type) {
        this.page_type = page_type;
    }

    public String getCustomer_level() {
        return customer_level;
    }

    public void setCustomer_level(String customer_level) {
        this.customer_level = customer_level;
    }

    public String getPartner_level() {
        return partner_level;
    }

    public void setPartner_level(String partner_level) {
        this.partner_level = partner_level;
    }

    public int getRule_number() {
        return rule_number;
    }

    public void setRule_number(int rule_number) {
        this.rule_number = rule_number;
    }

    public int getClick_number() {
        return click_number;
    }

    public void setClick_number(int click_number) {
        this.click_number = click_number;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getCreate_operator() {
        return create_operator;
    }

    public void setCreate_operator(String create_operator) {
        this.create_operator = create_operator;
    }

    public String getPublish_operator() {
        return publish_operator;
    }

    public void setPublish_operator(String publish_operator) {
        this.publish_operator = publish_operator;
    }

    public int getOptimistic() {
        return optimistic;
    }

    public void setOptimistic(int optimistic) {
        this.optimistic = optimistic;
    }

    public String getUpdate_time() {
        return update_time;
    }

    public void setUpdate_time(String update_time) {
        this.update_time = update_time;
    }

    public int getPv_value() {
        return pv_value;
    }

    public void setPv_value(int pv_value) {
        this.pv_value = pv_value;
    }

    public String getPublish_time() {
        return publish_time;
    }

    public void setPublish_time(String publish_time) {
        this.publish_time = publish_time;
    }

    public String getLink_url() {
        return link_url;
    }

    public void setLink_url(String link_url) {
        this.link_url = link_url;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getClick_type() {
        return click_type;
    }

    public void setClick_type(String click_type) {
        this.click_type = click_type;
    }

    public String getCreate_time() {
        return create_time;
    }

    public void setCreate_time(String create_time) {
        this.create_time = create_time;
    }

    public String getEnd_time() {
        return end_time;
    }

    public void setEnd_time(String end_time) {
        this.end_time = end_time;
    }

    public String getLink_title() {
        return link_title;
    }

    public void setLink_title(String link_title) {
        this.link_title = link_title;
    }

    public String getMessage_type() {
        return message_type;
    }

    public void setMessage_type(String message_type) {
        this.message_type = message_type;
    }

    public int getOptimistic_lastsync() {
        return optimistic_lastsync;
    }

    public void setOptimistic_lastsync(int optimistic_lastsync) {
        this.optimistic_lastsync = optimistic_lastsync;
    }

    public String getUpdate_operator() {
        return update_operator;
    }

    public void setUpdate_operator(String update_operator) {
        this.update_operator = update_operator;
    }

    public String getStart_time() {
        return start_time;
    }

    public void setStart_time(String start_time) {
        this.start_time = start_time;
    }

    public String getImage_path() {
        return image_path;
    }

    public void setImage_path(String image_path) {
        this.image_path = image_path;
    }

    public String getPopup_rule() {
        return popup_rule;
    }

    public void setPopup_rule(String popup_rule) {
        this.popup_rule = popup_rule;
    }

    public String getRegion() {
        return region;
    }

    public void setRegion(String region) {
        this.region = region;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

String json= "[{"publish_type":"00","uv_value":3,"app_type":"02","page_type":"","customer_level":"ALL_CUSTOMER","partner_level":"0","rule_number":0,"click_number":0,"title":"超时","create_operator":"zexin","publish_operator":"wangchaocheng","optimistic":0,"update_time":"2019-03-20 14:28:43","pv_value":10,"publish_time":"2019-03-20 14:28:51","link_url":"https://www.cnblogs.com/ailiailan/p/7388784.html","id":32,"click_type":"H5","create_time":"2019-02-26 09:36:33","end_time":"2019-03-30 10:00:04","link_title":"CNBLOGS","message_type":"02","optimistic_lastsync":0,"update_operator":"wangchaocheng","start_time":"2019-02-25 09:36:01","image_path":"http://.www.baidu.com","popup_rule":"02","region":"","status":"NORMAL"}]";

    List<mobileData> list = null;
    try {
        list = gson.fromJson(json, new TypeToken<List<mobileData>>(){}.getType());
    }catch (Exception e){
        e.printStackTrace();
    }`

感谢。
是的,这也是我目前采用的 ,但感觉很不舒服,既然我用了GsonConverterFactory,就势必想要一步到位,直接返回bean。我试图重写Converter但没有成功,我希望通过重写Converter来解决这个问题。

diov commented

这很明显是后端同学偷懒的结果,json 写成这样...我觉得与其在端上妥协,做这种 trick 的处理。还不如跟后端沟通一下,给过来标准的 json 格式。
另外我觉得 @bricklazy 提到的处理方式是最简单有效的。其实你也已经用了 RxJava,只需要再 map 一次就 ok 了。重写 Converter 就复杂了,而且也不通用。