Json 介绍
JsonObject 对应Json字符串中用{}包裹的数据,相当于一个实体类
JsonArray对应Json字符串中用[]包裹的数据,相当于一个数组
下面为从某个服务器中拉去的数据,其中data为数据核心部分,minfo为一个数组,其中包含所需要渲染的数据,filter为一个数据实体,包含筛选条件信息。
{
"status":"200",
"msg
":"success",
"source":"156",
"data":{
"data_type":"2",
"minfo":Array[30],
"filter":{
"orderby":[
{
"title":"Popular",
"id":"1"
},
Object{...},
Object{...}
],
"genre":Array[27],
"pub":Array[12],
"type":Array[3],
"country":Array[49]
}
}
}
创建对应格式化实体类
从服务器端拉去的Json字符串,需要创建对应的实体类进行接收,本文介绍一种插件,用于Android端格式化建立实体类
安装插件GsonFormatPlus
点击设置->plugins->搜索并安装插件GsonFormatPlus插件
创建实体类
第一步,在需要创建实体类的地方右击空白处,在弹出的显示框中选择Generate
第二步,然后在选择刚才安装的插件GsonFormatPlus 第三步,最后将Json字符串复制上去,点击OK即可自动创建
踩坑笔记
如果你不想一次性创建所有的Json数据对于的实体类,也就是说,你所请求的Json字符串你不想创建在一个实体类中,比如下面Json字符串为例,下面的minfo是一个数组,如果你想把这个数组内的数据单独建立一个实体类,你需要把这个字段定义为JsonArray类型,注意不是全大写,全大写是另外一个类,会出错,JsonObject同理。这样可以让数据更加层次分明,在不同的地方引用时,较为方便。
private JsonArray orderby;
{
"status":"200",
"msg
":"success",
"source":"156",
"data":{
"data_type":"2",
"minfo":Array[30],
"filter":{
"orderby":[
{
"title":"Popular",
"id":"1"
},
Object{...},
Object{...}
],
"genre":Array[27],
"pub":Array[12],
"type":Array[3],
"country":Array[49]
}
}
}
Json数据解析
引入依赖
implementation 'com.squareup.okhttp3:okhttp:3.1.0'
implementation 'com.squareup.okio:okio:1.5.0'
implementation 'com.google.code.gson:gson:2.8.0'
OkHttp封装
将请求体用map进行键值对进行添加,然后使用表单进行提交。在建立Request对象将请求体进行上传,然后在newCall中接受服务器回调,此类是一个封装类,只取出第一层数据体,因为不同的接口所返回的数据内容不一样,Json体也不一样,所有此处只对第一层进行解析,然后在不同的地方调用时,在进行具体解析。
/**
* @param url connect server address
* @param map request param
* @param callback bind success or fail callback*/
public void Post(String url,Map<String,Object> map,HttpCallback callback) {
OkHttpClient client = new OkHttpClient();
FormBody.Builder requestBuild = new FormBody.Builder();
for (Map.Entry<String,Object> mEntry : map.entrySet()) {
requestBuild.add(mEntry.getKey(),mEntry.getValue()+"");
}
RequestBody requestBody = requestBuild.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("getInternetData","error message = "+e.getMessage());
callback.onFailure(ErrorParam.POSTINGERROR);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String body = response.body().string();
int code = response.code();
if (code == 200){
try {
JSONObject jsonObject = new JSONObject(body);
int status_code = jsonObject.getInt("status");
if (status_code == 200){
String data = jsonObject.getString("data");
callback.onResponse(data);
}else {
callback.onFailure(ErrorParam.NETWORKERROR);//net error
}
} catch (JSONException e) {
Log.e("getBannerData","error");
callback.onFailure(ErrorParam.RESOLVINGERROR);//resolve error
e.printStackTrace();
}
}else {
callback.onFailure(ErrorParam.SERVERERROR);//service error
}
}
});
}
JsonObject解析
* resolve jsonboject*/
public static <T> T fromJson(String josn,Class<T> c){
Gson gson = new Gson();
T t = null;
return t = gson.fromJson(josn,c);
}
JsonArray解析
public static <T> List<T> fromListJson(String json,Class<T> c){
List<T> list = new ArrayList<>();
Gson gson = new Gson();
JsonArray array = new JsonParser().parse(json).getAsJsonArray();
for (final JsonElement element: array) {
list.add(gson.fromJson(element,c));
}
return list;
}
回调
建立一个回调接口,将解析结果暴露给外部
public interface HttpCallback<T> {
void onFailure(int error);
void onResponse(T data) throws JSONException;
}
完整封装
因为隐私,服务器接口和请求体暂不外露,其余内容如下所示
public class OKHttpUtils {
private static Map<String,Object> map = new HashMap<>();
private static OKHttpUtils singleton;
private OKHttpUtils(){
}
public static OKHttpUtils getInstance(){
if (singleton == null){
Sync();
}
return singleton;
}
private static synchronized void Sync(){
if (singleton == null){
singleton = new OKHttpUtils();
InitMap();
}
}
/**
* @param url connect server address
* @param map request param
* @param callback bind success or fail callback*/
public void Post(String url,Map<String,Object> map,HttpCallback callback) {
OkHttpClient client = new OkHttpClient();
FormBody.Builder requestBuild = new FormBody.Builder();
for (Map.Entry<String,Object> mEntry : map.entrySet()) {
requestBuild.add(mEntry.getKey(),mEntry.getValue()+"");
}
RequestBody requestBody = requestBuild.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("getInternetData","error message = "+e.getMessage());
callback.onFailure(ErrorParam.POSTINGERROR);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String body = response.body().string();
Log.d("sss",body.toString());
int code = response.code();
if (code == 200){
try {
JSONObject jsonObject = new JSONObject(body);
int status_code = jsonObject.getInt("status");
if (status_code == 200){
String data = jsonObject.getString("data");
callback.onResponse(data);
}else {
callback.onFailure(ErrorParam.NETWORKERROR);//net error
}
} catch (JSONException e) {
Log.e("getBannerData","error");
callback.onFailure(ErrorParam.RESOLVINGERROR);//resolve error
e.printStackTrace();
}
}else {
callback.onFailure(ErrorParam.SERVERERROR);//service error
}
}
});
}
/**
* public request param*/
private static void InitMap(){
//因为隐私,请求体省略
}
public Map<String,Object> getMap(){
return map;
}
public String setUrl(String port){
return PortParam.BaseUrl+port;
}
/**
* resolve jsonboject*/
public static <T> T fromJson(String josn,Class<T> c){
Gson gson = new Gson();
T t = null;
return t = gson.fromJson(josn,c);
}
/**
* resolve jsonarray*/
public static <T> List<T> fromListJson(String json,Class<T> c){
List<T> list = new ArrayList<>();
Gson gson = new Gson();
JsonArray array = new JsonParser().parse(json).getAsJsonArray();
for (final JsonElement element: array) {
list.add(gson.fromJson(element,c));
}
return list;
}
}
Json解析
然后在外部进行服务器地址、请求体上传,在进行进一步解析,在下面通过刚刚建立的回调接口,在OnFailure()中进行错误解析回调,并处理;在OnResponse()中进行json字符串获取,此字符串已经被解析了一层,在根据不同的接口回调,做出不同响应即可,此处将获取的json字符串转为数组形式。
private void Post(){
OKHttpUtils utils = OKHttpUtils.getInstance();
Map<String,Object> map = utils.getMap();
//内容省略...map.put("","");
utils.Post(utils.setUrl(PortParam.TvShowsPort), map, new HttpCallback() {
@Override
public void onFailure(int error) {
switch (error){
case ErrorParam.NETWORKERROR:
break;
case ErrorParam.SERVERERROR:
break;
case ErrorParam.RESOLVINGERROR:
break;
case ErrorParam.POSTINGERROR:
handler.sendEmptyMessage(4);
break;
}
}
@Override
public void onResponse(Object data) throws JSONException {
array = new JSONArray(data.toString());
handler.sendEmptyMessage(0);
}
});
}
然后使用rxjava进行监听,此框架一目了然,subscribe()建立被观察者,subscribe()建立观察者,然后onNext()、onComplete(),此处回调的数据较多,又分为不同的场景,头部有一个轮播图baner数据,下面有一个RecyclerView嵌套RecyclerView,需要根据判断解析的Display_type 判断其显示方式,从而决定RecyclerView是横向显示还是竖向显示。最后通过handler异步渲染UI。
private void UpdateUI(){
Observable.create(new ObservableOnSubscribe<FeaturedData>() {
@Override
public void subscribe(@NotNull ObservableEmitter<FeaturedData> observableEmitter) throws Exception {
if (featuredDataList != null){
for (int i = 0; i < featuredDataList.size(); i++) {
if (featuredDataList.get(i).getData_type().equals("1")){
observableEmitter.onNext(featuredDataList.get(i));
}
}
observableEmitter.onComplete();
}
}
}).subscribe(new Observer<FeaturedData>() {
@Override
public void onSubscribe(@NotNull Disposable disposable) {
}
@Override
public void onNext(@NotNull FeaturedData featuredData) {
if (featuredData.getName().equals("Banner")){
try {
JSONArray array = new JSONArray(featuredData.getData().toString());
featureBannerDataList = OKHttpUtils.fromListJson(array.toString(),FeatureBannerData.class);
//update banner
handler.sendEmptyMessage(2);
} catch (JSONException e) {
e.printStackTrace();
}
}else if (featuredData.getDisplay_type().equals("1")){
//v
JSONArray jsonArray = null;
JSONObject object = null;
try {
jsonArray = new JSONArray(featuredData.getData().toString());
object = jsonArray.getJSONObject(0);
} catch (JSONException e) {
e.printStackTrace();
}
FeatureInnerData data = OKHttpUtils.fromJson(object.toString(),FeatureInnerData.class);
data.setSlide_way(1);
featureInnerDataList.add(data);
}else {
//H
JSONArray jsonArray = null;
JSONObject object = null;
try {
jsonArray = new JSONArray(featuredData.getData().toString());
object = jsonArray.getJSONObject(0);
} catch (JSONException e) {
e.printStackTrace();
}
FeatureInnerData data = OKHttpUtils.fromJson(object.toString(),FeatureInnerData.class);
data.setSlide_way(2);
featureInnerDataList.add(data);
}
}
@Override
public void onError(@NotNull Throwable throwable) {
}
@Override
public void onComplete() {
handler.sendEmptyMessage(3);
}
});
}
|