在网络网通信传输json数据格式的时候,有时候Json的数据格式并不是标准的json数据格式。这个时候在使用Gson ,fastJson 等框架去解析的时候回出现异常,例如 Expected BEGIN_OBJECT but was STRING,造成这种异常的原因有
第一:返回的json数据和要期望解析成的格式不对应,这个时候只要修改本地期望解析格式和json格式保持一致即可
第二:返回的json格式不是标准的json格式,这个时候就要获取json的源数据,然后找到json数据格式错误的地方,将不标准的json转换成标准的json在去解析。这就用到自定义解析json。
正常使用Retrofit2+Rxjava+OKhttp3的格式为:
封装Retrofit2:
package scj.jl.com.jlscjsockeserver.fujianinetworkbean.network.retrofit;
import android.util.Log;
import com.google.gson.Gson;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
public class BaseRetrofit {
private String tag = BaseRetrofit.class.getSimpleName();
private static final int DEFAULT_WRITE_TIME_OUT = 10;
private static final int DEFAULT_READ_TIME_OUT = 10;
private static final int DEFAULT_TIME_OUT = 20;//超时时间 10s
private Retrofit mRetrofit;
private static BaseRetrofit instance = null;
/**
* 获取BaseRetrofit
* @return
*/
public static BaseRetrofit getInstance(){
if (instance == null){
synchronized (BaseRetrofit.class){
if (instance == null){
instance = new BaseRetrofit();
}
}
}
return instance;
}
private BaseRetrofit(){
HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(new HttpLogger());
logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
OkHttpClient builder = new OkHttpClient().newBuilder()
.addInterceptor(logInterceptor)
.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS)
.writeTimeout(DEFAULT_WRITE_TIME_OUT,TimeUnit.SECONDS)
.readTimeout(DEFAULT_READ_TIME_OUT,TimeUnit.SECONDS)
.sslSocketFactory(sslContext.getSocketFactory()) //过滤所有证书
.hostnameVerifier(new AllowAllHostnameVerifier())
.build();
// 创建Retrofit
if (mRetrofit == null){
mRetrofit = new Retrofit.Builder()
// .addConverterFactory(CustomizeGsonConverterFactory.create()) 自定义ConverterFactory
.addConverterFactory(GsonConverterFactory.create(new Gson()))使用官方的ConverterFactory
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(builder)
.baseUrl(HttpUrlConfig.BaseServerUrl)
.build();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取对应的Service
* @param service Service 的 class
* @param
* @return
*/
public
return mRetrofit.create(service);
}
public class HttpLogger implements HttpLoggingInterceptor.Logger {
@Override
public void log(String message) {
Log.d("HttpLogInfo", message);
}
}
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] x509Certificates,
String s) throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] x509Certificates,
String s) throws java.security.cert.CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
} };
}
接口封装:
package scj.jl.com.jlscjsockeserver.fujianinetworkbean.network.retrofit; import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.Headers; import retrofit2.http.POST; import rx.Observable; import scj.jl.com.jlscjsockeserver.fujianinetworkbean.bean.BaseRequestBean; import scj.jl.com.jlscjsockeserver.fujianinetworkbean.bean.BaseResponsBean; import scj.jl.com.jlscjsockeserver.fujianinetworkbean.bean.LoginModel; public interface NetInterface { @Headers({"Content-Type: application/json","Accept: application/json"}) @POST("/") Observablerequest(@Body BaseRequestBean baseRequestBean); @Headers({"Content-Type: application/json","Accept: application/json"}) @POST("/") Observable request2(@Body BaseRequestBean baseRequestBean); }
接口调用封装:
package scj.jl.com.jlscjsockeserver.fujianinetworkbean.network.retrofit;
import com.google.gson.Gson;
import retrofit2.Callback;
import rx.Observable;
import rx.Observer;
import scj.jl.com.jlscjsockeserver.fujianinetworkbean.bean.BaseRequestBean;
import scj.jl.com.jlscjsockeserver.fujianinetworkbean.bean.BaseResponsBean;
import scj.jl.com.jlscjsockeserver.fujianinetworkbean.bean.LoginModel;
import scj.jl.com.jlscjsockeserver.fujianinetworkbean.bean.ToolsUtils;
import scj.jl.com.utillibrary.log.LogUtil;
/**
* Created by jl on 2020/5/26.
*/
public class ApiNet extends BaseNet{
private String TAG = "ApiNet";
private static NetInterface mNetInterface;
private static ApiNet instance = null;
public static ApiNet getInstance(){
if (instance == null){
instance = new ApiNet();
mNetInterface = BaseRetrofit.getInstance().create(NetInterface.class);
}
return instance;
}
/**
* 请求接口
* @param baseRequestBean
* @return
*/
public Observable
return mNetInterface.request(baseRequestBean);
}
}
引用
implementation 'com.squareup.retrofit2:retrofit:2.2.0' implementation 'com.squareup.retrofit2:converter-gson:2.2.0' implementation 'com.squareup.retrofit2:adapter-rxjava:2.2.0' implementation 'com.squareup.okhttp3:logging-interceptor:3.5.0' implementation 'com.squareup.okhttp3:okhttp:3.2.0'
当需要自定义的时候我们自己重写Converter.Factory
package scj.jl.com.jlscjsockeserver.fujianinetworkbean.network.retrofit;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;
import scj.jl.com.utillibrary.log.LogUtil;
/**
* Created by jl on 2020/5/27.
*/
public class CustomizeGsonConverterFactory extends Converter.Factory {
private static final String TAG = CustomizeGsonConverterFactory.class.getSimpleName();
public static CustomizeGsonConverterFactory create() {
return create(new Gson());
}
public static CustomizeGsonConverterFactory create(Gson gson) {
return new CustomizeGsonConverterFactory(gson);
}
private final Gson gson;
private CustomizeGsonConverterFactory(Gson gson) {
if (gson == null) {
throw new NullPointerException("gson == null");
}
this.gson = gson;
}
@Override
public Converter
// return super.responseBodyConverter(type, annotations, retrofit);
LogUtil.d(TAG,"type"+type);
//自定义的请求响应处理
TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type));
return new CustomizeGsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
// return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);
// 自定义的请求处理
TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type));
return new CustomizeGsonRequestBodyConverter<>(gson, adapter);
}
}
自定义的请求
package scj.jl.com.jlscjsockeserver.fujianinetworkbean.network.retrofit;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import retrofit2.Converter;
/**
这里没有任何改变
* Created by jl on 2020/5/27.
*/
public class CustomizeGsonRequestBodyConverter
private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter
CustomizeGsonRequestBodyConverter(Gson gson, TypeAdapter
this.gson = gson;
this.adapter = adapter;
}
@Override
public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
自定义的响应
package scj.jl.com.jlscjsockeserver.fujianinetworkbean.network.retrofit;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import scj.jl.com.jlscjsockeserver.fujianinetworkbean.bean.BaseResponsBean;
import scj.jl.com.utillibrary.log.LogUtil;
/**
* Created by jl on 2020/5/27.
*/
public class CustomizeGsonResponseBodyConverter
private static final String TAG = CustomizeGsonResponseBodyConverter.class.getSimpleName();
private final Gson gson;
private final TypeAdapter
private BaseResponsBean baseResponsBean = null;
CustomizeGsonResponseBodyConverter(Gson gson, TypeAdapter
this.gson = gson;
this.adapter = adapter;
}
@Override
public T convert(ResponseBody value) throws IOException {
String respones = value.string();//将json数据转化成字符串
//在这里处理需要处理的json数据
// BaseResponsBean bastR = gson.fromJson(respones,BaseResponsBean.class);
// if (bastR.getCmdType().equals("07")){
// String tempStr = respones.replace("\\\"{","\"{");
// String afterTempStr = tempStr.replace("}\\\"","}\"");
// String strs = afterTempStr.replace("\\","");
// String strs1 = strs.replace("\"{","{");
// String strs2 = strs1.replace("}\"","}");
// LogUtil.d(TAG,"strs2 = "+strs2);
// baseResponsBean = gson.fromJson(strs2,BaseResponsBean.class);
// return adapter.fromJson(respones);
// }else {
return adapter.fromJson(respones);
// }
}
}
最后修改我们封装的Retrofit,添加ConverterFactory的时候添加我们自定一个ConverterFactory。