一、什么是JSON,JSON的作用是什么,如何编写JSON?
JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。采用完全独立于编程语言的文本格式来存储和表示数据.
简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言.
例如:
一个java对象转换成json对象以后是什么样子?
public class Person {
private int perid;
private String pername;
private int perage;
private String peraddress;
getXXX()/setXXX();
}
//创建一个person类的对象
Person person1=new Person();
person1.setPerid(1001);
person1.setPername("zhangsan");
person1.setPerage(23);
person1.setPeraddress("西安");
//将person1这个java对象转换成json对象对应的字符串数据
{"perid":1001,"pername":"zhangsan","perage":23,"peraddress":"西安"}
上面是将一个java对象写成json的样子。
假设现在有一组对象需要写成json的样子,那应该怎么写?
Person person1=new Person();
person1.setPerid(1001);
person1.setPername("zhangsan");
person1.setPerage(23);
person1.setPeraddress("西安");
Person person2=new Person();
person2.setPerid(1002);
person2.setPername("lisi");
person2.setPerage(24);
person2.setPeraddress("北京");
Person person3=new Person();
person3.setPerid(1003);
person3.setPername("wangwu");
person3.setPerage(25);
person3.setPeraddress("上海");
//创建一个保存person对象的集合
List<Person> personlist=new ArrayList<Person>();
//将上面创建的3个person对象保存到集合中
personlist.add(person1);
personlist.add(person2);
personlist.add(person3);
将保存java对象的集合写成json的样子。:
[
{"perid":1001,"pername":"zhangsan","perage":23,"peraddress":"西安"},
{"perid":1002,"pername":"lisi","perage":24,"peraddress":"北京"},
{"perid":1003,"pername":"wangwu","perage":25,"peraddress":"上海"}
]
注意:
- 用一组“{}”包围键/值对组合,键/值对组合中的键名写在前面并用双引号 "" 包裹,使用冒号 : 分隔,然后紧接着值,多个键/值对组合中间用“,”分隔,这就表示一个json对象。
- 用一组“[]”包围值/json对象这就表示一个json数组。json数组是用来保存java数组数据/集合数据。
- json对象中数字值和布尔值是不需要双引号。
通常情况下我们所遇到的json数据都是json对象中包含json数组,json数组中又包含json对象的复杂形式。
例如:
/**
* 保存地址信息的java类
* @author Administrator
*
*/
public class PersonAddress {
private String type; //地址类型【家庭/工作】
private String info; //地址信息
.......
}
public class Person {
private int perid;
private String pername;
private int perage;
//保存地址信息的数组
private PersonAddress peraddress[];
.......
}
创建3个person类的对象 将创建的person对象存储至集合中
//创建3个person类的对象
Person person1=new Person();
person1.setPerid(1001);
person1.setPername("zhangsan");
person1.setPerage(23);
//创建保存地址信息的数组
PersonAddress peraddress[]=new PersonAddress[2];
//创建两个地址的对象
PersonAddress address1=new PersonAddress();
address1.setType("home");
address1.setInfo("西安");
PersonAddress address2=new PersonAddress();
address2.setType("work");
address2.setInfo("北京");
//将创建好的地址对象装入数组
peraddress[0]=address1;
peraddress[1]=address2;
person1.setPeraddress(peraddress);
Person person2=new Person();
person2.setPerid(1002);
person2.setPername("lisi");
person2.setPerage(24);
//创建保存地址信息的数组
PersonAddress peraddress2[]=new PersonAddress[2];
//创建两个地址的对象
PersonAddress address21=new PersonAddress();
address21.setType("home");
address21.setInfo("上海");
PersonAddress address22=new PersonAddress();
address22.setType("work");
address22.setInfo("重庆");
//将创建好的地址对象装入数组
peraddress2[0]=address21;
peraddress2[1]=address22;
person2.setPeraddress(peraddress2);
Person person3=new Person();
person3.setPerid(1003);
person3.setPername("wangwu");
person3.setPerage(25);
//创建保存地址信息的数组
PersonAddress peraddress3[]=new PersonAddress[2];
//创建两个地址的对象
PersonAddress address31=new PersonAddress();
address31.setType("home");
address31.setInfo("广州");
PersonAddress address32=new PersonAddress();
address32.setType("work");
address32.setInfo("西安");
//将创建好的地址对象装入数组
peraddress3[0]=address31;
peraddress3[1]=address32;
person3.setPeraddress(peraddress3);
//创建一个保存person对象的集合
List<Person> personlist=new ArrayList<Person>();
//将创建的person对象存储至集合中
personlist.add(person1);
personlist.add(person2);
personlist.add(person3);
将上面的集合转换成json数据字符串以后是什么样子???
[
{ "perid":1001,
"pername":"zhangsan",
"perage":23,
"peraddress":[
{"type":"home","info":"西安"},
{"type":"work","info":"北京"}
]----json数组
}, -- json对象
{"perid":1002,
"pername":"lisi",
"perage":24,
"peraddress":[
{"type":"home","info":"上海"},
{"type":"work","info":"重庆"}
]
},
{"perid":1003,
"pername":"wangwu",
"perage":25,
"peraddress":[
{"type":"home","info":"广州"},
{"type":"work","info":"西安"}
]
}
]
当我们得到一个极其复杂的json数据后,搞不清楚这个json数据的结构。我们可以利用工具【https://www.json.cn/】得到明晰的json数据的结构。
二、JSON数据的生成方式和解析方式
2.1 JSON数据的生成【java对象---json数据】
1.json-simple-1.1.jar第三方的开发包生成json数据
/**
* 1.使用第三方开发包【json-simple-1.1.jar】 生成json数据
*/
public static String createJosnByjsonsimple(List<Person> personlist){
String jsoninfo="";
//创建json数组
JSONArray jsonarray=jsonarray=new JSONArray();
//遍历集合得到person对象
for(Person person:personlist){
//创建JSON对象
JSONObject jsonObject=new JSONObject();
//向JSON中存放数据
jsonObject.put("perid", person.getPerid());
jsonObject.put("pername", person.getPername());
jsonObject.put("perage", person.getPerage());
//创建保存peraddress对象的JOSNArray数组对象
JSONArray jsperaddress=new JSONArray();
for (PersonAddress personAddress : person.getPeraddress()) {
//创建保存地址对象的json对象
JSONObject jsObjaddress=new JSONObject();
jsObjaddress.put("type", personAddress.getType());
jsObjaddress.put("info", personAddress.getInfo());
//将保存地址对象的json对象 保存在json数组中
jsperaddress.add(jsObjaddress);
}
//将保存地址的json数组保存到JSON对象中
jsonObject.put("peraddress", jsperaddress);
//将保存了数据的jsonObject对象保存到jsonarray集合中
jsonarray.add(jsonObject);
}
jsoninfo=jsonarray.toJSONString();
return jsoninfo;
}
gson-2.8.0.jar第三方的开发包生成json数据
/**
* 2.gson-2.8.0.jar第三方的开发包生成json数据
*/
public static String createJsonBygson(List<Person> personlist){
String jsoninfo="";
jsoninfo=new Gson().toJson(personlist);
return jsoninfo;
}
3.jackson第三方的开发包生成json数据
public static String createJsonByjackson(List<Person> personlist){
String jsoninfo="";
try {
jsoninfo=new ObjectMapper().writeValueAsString(personlist);
} catch (JsonProcessingException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return jsoninfo;
}
2.2 JSON数据的解析【json数据---java对象】
1.json-simple-1.1.jar第三方的开发包解析json数据
/**
* 1.json-simple-1.1.jar第三方的开发包解析json数据
* @throws Exception
*/
public static List<Person> parseJsonByjsonsimple(String json) throws Exception{
//创建一个保存解析得到的person对象的集合
List<Person> personlist=new ArrayList<Person>();
//创建一个json解析器对象
JSONParser jsonParser=new JSONParser();
JSONArray perlistArray=(JSONArray) jsonParser.parse(json);
for (int i=0;i<perlistArray.size();i++) {
//创建一个保存数据的Person集合
Person person=new Person();
//从JSON数组中获取JSON对象,并保存
JSONObject jsonObject=(JSONObject)perlistArray.get(i);
//获取数据
int perid=Integer.parseInt(jsonObject.get("perid").toString()) ;
String pername=(String)jsonObject.get("pername");
int perage=Integer.parseInt(jsonObject.get("perage").toString());
//获取保存地址的JSON数组
JSONArray jsonArray=(JSONArray)jsonObject.get("peraddress");
//创建要保存在person中的地址数组对象
PersonAddress[] personAddress=new PersonAddress[jsonArray.size()];
for (int j=0;j<jsonArray.size();j++) {
//创建保存地址数据的对象
PersonAddress address=new PersonAddress();
//得到JSON数组中保存的JSON对象
JSONObject addressObj=(JSONObject)jsonArray.get(j);
//得到JSON对象中保存的地址数据值
String type=(String)addressObj.get("type");
String info=(String)addressObj.get("info");
//保存数据值到地址对象中
address.setType(type);
address.setInfo(info);
//保存地址对象到--地址数组对象中
personAddress[j]=address;
}
person.setPerid(perid);
person.setPername(pername);
person.setPerage(perage);
person.setPeraddress(personAddress);
//保存Person对象到Personlist集合中
personlist.add(person);
}
return personlist;
}
2.gson-2.8.0.jar第三方的开发包解析json数据
public static List<Person> parseJsonByGson(String json){
Gson gson=new Gson();
//formJson(String,Class)
//formJson(String,Type)
//formJson(Reader,Class)
//formJson(Reader,Type)
//匿名内部类
Type type=new TypeToken<List<Person>>() {
}.getType();
return gson.fromJson(json,type);
}
3.jackson第三方的开发包解析json数据
public static List<Person> parseJson3()throws Exception {
List<Person> personlist=new ArrayList<Person>();
//创建解析器对象
ObjectMapper objectMapper=new ObjectMapper();
JsonNode personNodes=objectMapper.readTree(new FileReader("person1.json"));
for(int i=0;i<personNodes.size();i++) {
JsonNode personNode=personNodes.get(i);
int perid=personNode.get("perid").asInt();
String pername=personNode.get("pername").asText();
int perage=personNode.get("perage").asInt();
JsonNode personAddressNodes=personNode.get("peraddress");
PersonAddress peraddress[]=new PersonAddress[personAddressNodes.size()];
for(int j=0;j<personAddressNodes.size();j++) {
JsonNode addressNode=personAddressNodes.get(j);
String type=addressNode.get("type").asText();
String info=addressNode.get("info").asText();
PersonAddress address=new PersonAddress();
address.setType(type);
address.setInfo(info);
peraddress[j]=address;
}
Person person =new Person();
person.setPerid(perid);
person.setPername(pername);
person.setPerage(perage);
person.setPeraddress(peraddress);
personlist.add(person);
}
return personlist;
}
解析
(1)创建保存数据的类
天气类
package com.wangxing.tq.bean;
public class TianQiBean {
private String cityname; // 城市名称
private String fabushijian;// 天气信息的发布时间
private WeiLaiTianQi weiLaiTianQi[];// 数组--就是一组数据
public String getCityname() {
return cityname;
}
public void setCityname(String cityname) {
this.cityname = cityname;
}
public String getFabushijian() {
return fabushijian;
}
public void setFabushijian(String fabushijian) {
this.fabushijian = fabushijian;
}
public WeiLaiTianQi[] getWeiLaiTianQi() {
return weiLaiTianQi;
}
public void setWeiLaiTianQi(WeiLaiTianQi[] weiLaiTianQi) {
this.weiLaiTianQi = weiLaiTianQi;
}
}
未来天气类
package com.wangxing.tq.bean;
public class WeiLaiTianQi {
private String tianqiname;//保存天气名称
private String tianqidate;//保存那一天的天气时间
private String maxWD;//保存最高温度
private String minWD;//保存最低温度
private String fengxiang;//保存风向
private String fengli;//保存风力
public String getTianqiname() {
return tianqiname;
}
public void setTianqiname(String tianqiname) {
this.tianqiname = tianqiname;
}
public String getTianqidate() {
return tianqidate;
}
public void setTianqidate(String tianqidate) {
this.tianqidate = tianqidate;
}
public String getMaxWD() {
return maxWD;
}
public void setMaxWD(String maxWD) {
this.maxWD = maxWD;
}
public String getMinWD() {
return minWD;
}
public void setMinWD(String minWD) {
this.minWD = minWD;
}
public String getFengxiang() {
return fengxiang;
}
public void setFengxiang(String fengxiang) {
this.fengxiang = fengxiang;
}
public String getFengli() {
return fengli;
}
public void setFengli(String fengli) {
this.fengli = fengli;
}
}
(2)创建解析类
package com.wangxing.tq.util;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import com.wangxing.tq.bean.TianQiBean;
import com.wangxing.tq.bean.WeiLaiTianQi;
public class TianQiUtil {
private static final Object JSONObject = null;
/**
* 解析天气信息
* @throws Exception
*/
/*
* "basic":{
"city":"西安",
"cnty":"中国",
"id":"CN101110101",
"lat":"34.26316071",
"lon":"108.94802094",
"update":{
"loc":"2021-02-27 09:36",
"utc":"2021-02-27 01:36"
}
},
* */
public static TianQiBean getTianQiInfo(String tianqijson) throws Exception{
//获得保存信息的天气对象
TianQiBean tianQiBean=new TianQiBean();
//获取解析器
JSONParser jsonParser=new JSONParser();
//通过解析器获取解析对象,保存为JSON对象
JSONObject jsonObject=(JSONObject)jsonParser.parse(tianqijson);
//通过JSON对象获得KEY:HeWeather5的值对象,并保存为JSON数组对象
JSONArray heWeather5Array=(JSONArray)jsonObject.get("HeWeather5");
//通过heWeather5Array对象获得其数组中保存的第一个对象,并保存为JSON对象:heWeather5Objd
JSONObject heWeather5Obj=(JSONObject)heWeather5Array.get(0);
//通过heWeather5Obj对象获得对象中键“basic”的值对象,并保存为basicObj对象
JSONObject basicObj=(JSONObject)heWeather5Obj.get("basic");
//通过 basicObj对象获得对象中键“city”的值,保存为cityname
String cityName=(String)basicObj.get("city");
//添加到保存数据的TianQiBean对象中
tianQiBean.setCityname(cityName);
//通过basicObj对象获得对象中键“update”的值对象,保存为updateobj
/*
* :{"loc":"2021-02-27 09:36",
"utc":"2021-02-27 01:36"}
* */
JSONObject updateobj=(JSONObject)basicObj.get("update");
//通过updateobj对象中键“loc”获得值对象,保存为fabushijian
String fabushijian=(String)updateobj.get("loc");
//将fabushijian保存到tianqiBean中
tianQiBean.setFabushijian(fabushijian);
//创建要保存到tianqiBean中的WeiLaiTianQi[]
WeiLaiTianQi[] weiLaiTianQis=new WeiLaiTianQi[((JSONArray)heWeather5Obj.get("daily_forecast")).size()];
//通过heWeather5OneObj的键“daily_forecast”获得值对象,将值对象保存为数组,并且遍历数组拿到需要的元素
for(int i = 0;i<((JSONArray)heWeather5Obj.get("daily_forecast")).size();i++){
//获得daily_forecast值-数组对象的第i个对象
/*
* "daily_forecast":[
{"cond":{
"txt_d":"...",
}
},
{...}....
* */
JSONObject daily_forecastobj=(JSONObject) ((JSONArray)heWeather5Obj.get("daily_forecast")).get(i);
//在daily_forecastobj对象中通过键“cond”获取其所对应的值对象,通过值对象的“txt_d”键获得天气名称的值,并保存为String
//这样写的缺点是代码无法复用,很不好!,若是再想用cond对象中的数据值则得重写这段代码
String tqname=(String)((JSONObject)(daily_forecastobj.get("cond"))).get("txt_d");
//保存数据值,创建要保存在WeiLaiTianQi[]对象中的WeiLaiTianQi对象
WeiLaiTianQi weiLaiTianQi=new WeiLaiTianQi();
weiLaiTianQi.setTianqiname(tqname);
//获得那一天的天气时间数据值
//通过daily_forecastobj对象的键“date”获取其所对应的值,保存为datetime
String datetime=(String)daily_forecastobj.get("date");
//保存时间数据值
weiLaiTianQi.setTianqidate(datetime);
//获得温度
//通过daily_forecastobj对象的键“tmp”获取其所对应的值对象
JSONObject tmpObj=(JSONObject)daily_forecastobj.get("tmp");
//通过tmpObj对象的键“max”与“min”获得温度值
String wdmax=(String)tmpObj.get("max");
String wdmin=(String)tmpObj.get("min");
//保存数据值
weiLaiTianQi.setMaxWD(wdmax);
weiLaiTianQi.setMinWD(wdmin);
//获得风力数据值
//通过daily_forecastobj对象的键“wind”获取其所对应的值对象
JSONObject windObj=(JSONObject)daily_forecastobj.get("wind");
//通过windObj对象的键“dir”获得风向,“spd”获得风力
String fx=(String)windObj.get("dir");
String fl=(String)windObj.get("sc");
//保存数据值
weiLaiTianQi.setFengxiang(fx);
weiLaiTianQi.setFengli(fl);
//将weiLaiTianQi对象添加到WeiLaiTianQi[]对象中
weiLaiTianQis[i]=weiLaiTianQi;
}
tianQiBean.setWeiLaiTianQi(weiLaiTianQis);
//至此所有数据保存完毕
//返回tianQiBean对象
return tianQiBean;
}
}
创建获取天气JOSN信息类
package com.wangxing.tq.util;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class MyX509TrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
// 处理http请求 requestUrl为请求地址 requestMethod请求方式,值为"GET"或"POST"
public static String httpRequest(String requestUrl, String requestMethod,
String outputStr) {
StringBuffer buffer = null;
try {
URL url = new URL(requestUrl);// 请求地址
HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 创建连接对象
conn.setDoOutput(true);// 是否输出
conn.setDoInput(true);// 是否输入
conn.setRequestMethod(requestMethod);// post Or get
conn.setRequestProperty("Charset", "utf-8");
conn.setFollowRedirects(false);
conn.setInstanceFollowRedirects(false);
conn.connect();// 发起连接
// 往服务器端写内容 也就是发起http请求需要带的参数
if (null != outputStr) {
OutputStream os = conn.getOutputStream();
os.write(outputStr.getBytes("utf-8"));
os.close();
}
// 读取服务器端返回的内容
// PrintWriter out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(),"utf-8"));
// out.println(obj);
InputStream is = conn.getInputStream();
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
BufferedReader br = new BufferedReader(isr);
buffer = new StringBuffer();
String line = null;
while ((line = br.readLine()) != null) {
buffer.append(line);
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return buffer.toString();
}
/*
* 处理https GET/POST请求 请求地址、请求方法、参数
*/
public static String httpsRequest(String requestUrl, String requestMethod,
String outputStr) {
StringBuffer buffer = null;
try {
// 创建SSLContext
SSLContext sslContext = SSLContext.getInstance("SSL");
TrustManager[] tm = { new MyX509TrustManager() };
// 初始化
sslContext.init(null, tm, new java.security.SecureRandom());
// 获取SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestMethod(requestMethod);
// 设置当前实例使用的SSLSoctetFactory
conn.setSSLSocketFactory(ssf);
conn.connect();//发起连接
//往服务器端写内容
if (null!=outputStr) {
OutputStream os=conn.getOutputStream();
os.write(outputStr.getBytes("utf-8"));
os.close();
}
//读取服务器端返回的数据
//得到字节输入流
InputStream isInputStream=conn.getInputStream();
//将字节输入流转换成字符输入流,并设置转换格式
InputStreamReader inputStreamReader=new InputStreamReader(isInputStream, "utf-8");
//将字符输入流转换为字符缓冲流
BufferedReader bufferedReader=new BufferedReader(inputStreamReader);
buffer=new StringBuffer();
String line=null;
while((line=bufferedReader.readLine())!=null){
buffer.append(line);
}
bufferedReader.close();
} catch (Exception e) {
e.printStackTrace();
}
return buffer.toString();
}
}
//测试类
package com.wangxing.tq.test;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Scanner;
import com.wangxing.tq.bean.TianQiBean;
import com.wangxing.tq.bean.WeiLaiTianQi;
import com.wangxing.tq.util.MyX509TrustManager;
import com.wangxing.tq.util.TianQiUtil;
/**
* 天气JSON的测试类
* @author 14336
*
*/
public class TestMain {
public static void main(String[] args) throws Exception {
GetCityName();
}
private static void GetCityName() throws Exception {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入城市名称:");
String name=scanner.nextLine();
name=URLEncoder.encode(name, "UTF-8");
String string="https://free-api.heweather.com/v5/weather?city="+name+"&key=d7bd43af19c64994b62fc643e5d75272";
MyX509TrustManager mx=new MyX509TrustManager();
String tianqijson=mx.httpsRequest(string, "POST", null);
System.out.println("正在刷新");
Thread.sleep(1000);
TianQiBean tianQiBean=TianQiUtil.getTianQiInfo(tianqijson);
System.out.println(tianQiBean.getCityname()+" "+tianQiBean.getFabushijian());
for(WeiLaiTianQi weilai:tianQiBean.getWeiLaiTianQi()){
System.out.println(weilai.getTianqidate()+"\t"+weilai.getTianqiname()+"\t"+
weilai.getMaxWD()+"~"+weilai.getMinWD()+"\t"+weilai.getFengxiang()+"\t"+
weilai.getFengli());
}
}
}