1.首先,在dependencies依赖库添加GSON库的依赖:
implementation 'com.google.code.gson:gson:2.8.6'
2.有关GSON
GSON提供了fromJson()和toJson()两个直接用于解析和生成JSON数据的方法,前者实现反序列化,后者实现了序列化,同时每个方法都提供了重载。
序列化:Serialization,将Java对象转换成JSON字符串。
反序列化:Deserialization,JSON字符串转换为Java对象。
3.举例:
①将以下JSON字符串转换为Java对象:
{"name":"张三","age":20}
那我们就可以定义一个Person类,并加入name和age这两个属性:
class Person{
public String name;
public int age;
Person(String name,int age){
this.name = name;
this.age = age;
}
}
然后调用如下代码:
Gson gson = new Gson();
String jsonData = "{\"name\":\"张三\",\"age\":20}";
Person person = gson.fromJson(jsonData,Person.class);
意思是:创建了一个GSON对象和一个JSON字符串,然后通过GSON对象的fromJson()方法,将这个字符串转换为Person类的对象,那么该Person对象就是一个名字叫张三,年龄20岁的人了。
②将Java对象转换为JSON字符串:
Gson gson = new Gson();
Person person = new Person("张三",20);
String jsonData = gson.toJson(person); //这一步后会得到{"name":"张三","age":20}
③将JSON数组转换为Java对象:
这也是我们在开发中常用的,解析JSON数组需要用到TypeToken将期望解析成的数据类型传入到fromJson()方法中,如下:
List<RecipeBean> recipes = gson.fromJson(jsonData,new TypeToken<List<RecipeBean>>(){}.getType());
这里在TypeToken后的{}其实是:这里new生成的是一个匿名类的对象,该匿名类继承自TypeToken,{}代表匿名类的内部,只不过这个内部什么都没有写。
现在我们用这个方法解析以下菜谱大全接口(https://www.showapi.com/apiGateway/view/1164)返回的JSON字符串吧。
如下图:
可以看到,我们真正需要的数据是红框内的,在datas这个JSON数组中,有绿框内的12个属性:des,smallImg......
上图是官网中的返回数据举例,其实我们真实返回的数据还有时间,如下图:
所以一共是13个属性。
那么我们创建的JAVA类应当要有这十三个属性,如下代码:
package com.kotlin.activitystudy.pojo; import java.io.Serializable; import java.util.List; public class RecipeBean implements Serializable { private String cpName; private String ct; private String des; private String id; private String largeImg; private String smallImg; private String tip; private String type; private String type_v1; private String type_v2; private String type_v3; private List<StepBean> steps; private List<YlBean> yl; public String getCpName() { return cpName; } public void setCpName(String cpName) { this.cpName = cpName; } public String getCt() { return ct; } public void setCt(String ct) { this.ct = ct; } public String getDes() { return des; } public void setDes(String des) { this.des = des; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getLargeImg() { return largeImg; } public void setLargeImg(String largeImg) { this.largeImg = largeImg; } public String getSmallImg() { return smallImg; } public void setSmallImg(String smallImg) { this.smallImg = smallImg; } public String getTip() { return tip; } public void setTip(String tip) { this.tip = tip; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getType_v1() { return type_v1; } public void setType_v1(String type_v1) { this.type_v1 = type_v1; } public String getType_v2() { return type_v2; } public void setType_v2(String type_v2) { this.type_v2 = type_v2; } public String getType_v3() { return type_v3; } public void setType_v3(String type_v3) { this.type_v3 = type_v3; } public List<StepBean> getSteps() { return steps; } public void setSteps(List<StepBean> steps) { this.steps = steps; } public List<YlBean> getYl() { return yl; } public void setYl(List<YlBean> yl) { this.yl = yl; } }
应该有注意到以下两个属性:
private List<StepBean> steps;
private List<YlBean> yl;
观察返回的数据steps部分:
steps中的内容并不是JSON字符串,而是JSON数组,并且该数组中有content,imgUrl,orderNum三个字段。
所以,我们需要新建一个对应属性的Java类,如下:
package com.kotlin.activitystudy.pojo; import java.io.Serializable; public class StepBean implements Serializable { private String content; private String imgUrl; private int oderNum; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getImgUrl() { return imgUrl; } public void setImgUrl(String imgUrl) { this.imgUrl = imgUrl; } public int getOderNum() { return oderNum; } public void setOderNum(int oderNum) { this.oderNum = oderNum; } }
private List<StepBean> steps;的意思是steps是一个StepBean类型的泛型集合。有关泛型可参考之前的笔记:https://www.cnblogs.com/Xiang-MY/p/16060687.html
private List<YlBean> yl;同理,贴一下对应JAVA类的代码:
package com.java.cookbook.pojo; import java.io.Serializable; public class YlBean implements Serializable { private String ylName; private String ylUnit; public String getYlName() { return ylName; } public void setYlName(String ylName) { this.ylName = ylName; } public String getYlUnit() { return ylUnit; } public void setYlUnit(String ylUnit) { this.ylUnit = ylUnit; } }
到目前为止,算是做好了准备工作,接下来就是用Gson去解析,解析的代码也很少,如下:
List<RecipeBean> recipes = new Gson().fromJson(new JSONObject(jsonStr).getJSONObject("showapi_res_body").getJSONArray("datas").toString(),new TypeToken<List<RecipeBean>>(){}.getType());
可以看到,我们用了getJSONObject()和getJSONArray()这两个方法。这是系统自带的JSONObject方式解析JSON数据中的两个方法,如下:
绿框的JSONObject类中包含了很多个方法,相关函数介绍如下:
JSONObject getJSONObject(String key):如果JSONObject对象中的value是一个JSONObject对象,即根据key获取对应的JSONObject对象。
JSONObject getJSONArray(String key):如果JSONObject对象中的value是一个JSONObject数组,即根据key获取对应的JSONObject数组。Object get(String key):根据key值获取JSONObject中对应的value值,获取到的为Object类型,需要手动转换为需要的类型。
对应以上的内容,再看看返回的JSON数据:
可以看到,showapi_res_body需要用getJSONObject方法,而datas需要使用getJSONArray方法。
经历new JSONObject(jsonStr).getJSONObject("showapi_res_body").getJSONArray("datas").toString()后,我们就拿到了datas下的JSON数据,对应的JAVA在上面已经创建好了。
经过fromJson()方法后,我们就拿到了解析的数据,现在我们可以通过对象.属性的方式使用这些想要的数据了。
【备注:还有另一种方法,即不使用JSONObject,那么我们就需要创建Java类的时候要将返回的所有数据对应的属性考虑进去。(此处的java类只是考虑了datas下的属性)
即:需要创建ResponseClass类,该类下应该包含属性如下:
然后需要为"showapi_res_body"属性创建对应的泛型集合的java类BodyClass,该类的属性应该有:
然后,再为其datas属性创建对应泛型集合的java类。
总之就是一层层弄下去,可是显而易见,除了datas中的数据我们并不需要其余的,所以此处用了JSONObject方式只拿了datas对应的JSONObject数组。】
实战:
例如:我现在想要拿到蛋类菜谱集合中,序列号为2的菜品名称,并显示到屏幕上。
接在之前的OKHttp异步GET请求数据后:https://www.cnblogs.com/Xiang-MY/p/16694714.html
修改之前的NetUtil工具类,在数据请求成功的回调中加上对数据的解析,并将解析后的集合传回去。代码如下:
package com.kotlin.activitystudy.http; import android.util.Log; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.kotlin.activitystudy.pojo.RecipeBean; import org.json.JSONObject; import java.io.IOException; import java.util.List; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class NetUtil { public interface OnRecipeQueriedCallback{ void onSuccess(List<RecipeBean> recipes); void onFailure(Exception e); } public static void queryRecipe(String tag,final OnRecipeQueriedCallback callback){ OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder() .url(String.format("http://route.showapi.com/1164-1?showapi_appid=填自己的&type= %s&showapi_sign=填自己的",tag)) .build(); Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); callback.onFailure(e); } @Override public void onResponse(Call call, Response response) throws IOException { try { String jsonStr = response.body().string(); List<RecipeBean> recipes = new Gson().fromJson(new JSONObject(jsonStr).getJSONObject("showapi_res_body").getJSONArray("datas").toString(),new TypeToken<List<RecipeBean>>(){}.getType()); callback.onSuccess(recipes); }catch (Exception e){ callback.onFailure(e); } } }); } }
修改Activity的代码:
package com.kotlin.activitystudy.http; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.kotlin.activitystudy.R; import com.kotlin.activitystudy.pojo.RecipeBean; import java.util.List; public class OKHttpActivity2 extends AppCompatActivity { private Button btn_Request; private TextView responseText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_okhttp); btn_Request = findViewById(R.id.btn_sendRequest); responseText = findViewById(R.id.responseText); btn_Request.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { sendRequestWithHttpURLConnection(); } }); } private void sendRequestWithHttpURLConnection() { NetUtil.queryRecipe("蛋类", new NetUtil.OnRecipeQueriedCallback() { @Override public void onSuccess(List<RecipeBean> recipes) { runOnUiThread(new Runnable() { @Override public void run() { responseText.setText(recipes.get(2).getCpName()); } }); } @Override public void onFailure(Exception e) { runOnUiThread(new Runnable() { @Override public void run() { Log.d("OKHttpActivity2","网络错误"); } }); } }); } }
运行如下:
成功拿到了它的数据。
标签:String,void,json,private,JSON,import,解析,type,public From: https://www.cnblogs.com/Xiang-MY/p/16706263.html