1.Json 和 Xml
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、C++、C#、Java、JavaScript、Perl、Python等)。这些特性使JSON成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成(网络传输速率)。
[ XML ]
优点::
(1). 格式统一, 符合标准
(2). 容易与其他系统进行远程交互, 数据共享比较方便
缺点:
(1). XML文件格式文件庞大, 格式复杂, 传输占用带宽
(2). 服务器端和客户端都需要花费大量代码来解析XML, 不论服务器端和客户端代码变的异常复杂和不容易维护
(3). 客户端不同浏览器之间解析XML的方式不一致, 需要重复编写很多代码
(4). 服务器端和客户端解析XML花费资源和时间
[ JSON ]
优点:
(1). 数据格式比较简单, 易于读写, 格式都是压缩的, 占用带宽小
(2). 易于解析这种语言, 客户端JavaScript可以简单的通过eval()进行JSON数据的读取
(3). 支持多种语言, 包括ActionScript, C, C#, ColdFusion, Java, JavaScript, Perl, PHP, Python, Ruby等语言服务器端语言, 便于服务器端的解析
(4). 在PHP世界, 已经有PHP-JSON和JSON-PHP出现了, 便于PHP序列化后的程序直接调用. PHP服务器端的对象、数组等能够直接生JSON格式, 便于客户端的访问提取.
(5). 因为JSON格式能够直接为服务器端代码使用, 大大简化了服务器端和客户端的代码开发量, 但是完成的任务不变, 且易于维护
缺点:
(1). 没有XML格式这么推广的深入人心和使用广泛, 没有XML那么通用性
(2). JSON格式目前在Web Service中推广还属于初级阶段
2.JSON语法
JSON 语法是 JavaScript 对象表示语法的子集。
- 数据在键值对中
- 数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
JSON 名称/值对
JSON 数据的书写格式是:名称/值对。
名称/值对组合中的名称写在前面(在双引号中),值对写在后面(同样在双引号中),中间用冒号隔开:
"firstName":"John"
这很容易理解,等价于这条 JavaScript 语句:
firstName="John"
jsonobject json对象。
{
mts:‘1351234‘,
province:‘重庆‘,
catName:‘中国移动‘,
telString:‘13512345678‘,
areaVid:‘29404‘,
ispVid:‘3236139‘,
carrier:‘重庆移动‘
}
3.下面结合一个案例,说明Android下如何通过网络访问解析Json数据:
(1)我们新建一个Android项目,如下:
(2)布局文件activity_main.xml:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" 6 tools:context="com.himi.json.MainActivity" > 7 8 <EditText 9 android:id="@+id/et_phone" 10 android:layout_width="match_parent" 11 android:layout_height="wrap_content" 12 android:hint="请输入电话号码" 13 android:inputType="phone"/> 14 <Button 15 android:layout_width="match_parent" 16 android:layout_height="wrap_content" 17 android:text="查询" 18 android:onClick="click" 19 /> 20 21 </LinearLayout>
布局效果图如下:
(3)我们获得网络端的Json数据是如下格式的:
我们要知道真正的JSON数据实体是:就是大括号包裹的部分就是JSON数据,这里就是没有"_GetZoneResult_= "(末尾含有一个空格)
{
mts:‘1351234‘,
province:‘重庆‘,
catName:‘中国移动‘,
telString:‘13512345678‘,
areaVid:‘29404‘,
ispVid:‘3236139‘,
carrier:‘重庆移动‘
}
回到MainActivity.java:
1 package com.himi.json; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.net.HttpURLConnection; 6 import java.net.MalformedURLException; 7 import java.net.ProtocolException; 8 import java.net.URL; 9 10 import org.json.JSONObject; 11 12 import android.app.Activity; 13 import android.os.Bundle; 14 import android.view.View; 15 import android.widget.EditText; 16 import android.widget.Toast; 17 18 public class MainActivity extends Activity { 19 private EditText et_phone; 20 21 @Override 22 protected void onCreate(Bundle savedInstanceState) { 23 super.onCreate(savedInstanceState); 24 setContentView(R.layout.activity_main); 25 et_phone = (EditText) findViewById(R.id.et_phone); 26 27 28 29 } 30 31 public void click(View view) { 32 String phone = et_phone.getText().toString().trim(); 33 final String path = "http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel="+phone; 34 35 new Thread() { 36 public void run() { 37 try { 38 URL url = new URL(path); 39 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 40 conn.setRequestMethod("GET"); 41 conn.setConnectTimeout(5000); 42 conn.setReadTimeout(5000); 43 int code = conn.getResponseCode(); 44 if (code == 200) { 45 // 得打JOSN数据,字符串 46 InputStream is = conn.getInputStream(); 47 String json = StreamTools.readStream(is).replace("_GetZoneResult_= ", ""); 48 //System.out.println(json); 49 JSONObject jsonObject = new JSONObject(); 50 final String catName = jsonObject.getString("catName"); 51 final String province = jsonObject.getString("province"); 52 runOnUiThread(new Runnable() { 53 public void run() { 54 Toast.makeText(MainActivity.this, "运营商: "+catName+"\n归属地: "+province, 55 0).show(); 56 }; 57 }); 58 } else { 59 runOnUiThread(new Runnable() { 60 public void run() { 61 Toast.makeText(MainActivity.this, "资源没有找到或者是服务器出了问题",0).show(); 62 }; 63 }); 64 65 } 66 } catch (Exception e) { 67 // TODO 自动生成的 catch 块 68 e.printStackTrace(); 69 runOnUiThread(new Runnable() { 70 public void run() { 71 Toast.makeText(MainActivity.this, "访问网络失败",0).show(); 72 }; 73 }); 74 75 } 76 }; 77 }.start(); 78 } 79 80 81 }
Toast土司是更新UI操作,它是不能出现在子线程new Thread()之中的,之前说过这里可以使用handler消息机制通知主线程进行UI更新,这里有了更加方便的API就是runOnUiThread()方法,这个方法的源码如下:
1 public final void runOnUiThread(Runnable action) { 2 if (Thread.currentThread() != mUiThread) { 3 mHandler.post(action); 4 } else { 5 action.run(); 6 } 7 }
这个方法将Runnable接口内部执行的内容在主线程执行;
这里源码可以看出它是先判断当前线程是否是UI主线程,不是的话就利用handler发送消息给主线程进行相应操作,如果当前线程是主线程,就直接在当前线程中执行。
还有这里利用我们之前自己编写的一个API,将流转化为字符串的工具类StreamTools:
1 package com.himi.json; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 7 /** 8 * 流的工具类 9 * 10 * @author Administrator 11 * 12 */ 13 public class StreamTools { 14 /** 15 * 把输入流的内容转换成字符串 16 * 17 * @param is 18 * @return null解析失败, string读取成功 19 */ 20 public static String readStream(InputStream is) { 21 try { 22 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 23 byte[] buffer = new byte[1024]; 24 int len = -1; 25 while ((len = is.read(buffer)) != -1) { 26 baos.write(buffer, 0, len); 27 } 28 is.close(); 29 String temptext = new String(baos.toByteArray()); 30 return new String(baos.toByteArray(), "gbk"); 31 } catch (IOException e) { 32 e.printStackTrace(); 33 return null; 34 } 35 } 36 }
(4)其实上面出现了很多的runOnUiThread(),我们可以抽取一个方法包裹这部分代码:
代码优化如下:
1 package com.himi.json; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.net.HttpURLConnection; 6 import java.net.MalformedURLException; 7 import java.net.ProtocolException; 8 import java.net.URL; 9 10 import org.json.JSONObject; 11 12 import android.app.Activity; 13 import android.os.Bundle; 14 import android.view.View; 15 import android.widget.EditText; 16 import android.widget.Toast; 17 18 public class MainActivity extends Activity { 19 private EditText et_phone; 20 21 @Override 22 protected void onCreate(Bundle savedInstanceState) { 23 super.onCreate(savedInstanceState); 24 setContentView(R.layout.activity_main); 25 et_phone = (EditText) findViewById(R.id.et_phone); 26 27 28 29 } 30 31 public void click(View view) { 32 String phone = et_phone.getText().toString().trim(); 33 final String path = "http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel="+phone; 34 35 new Thread() { 36 public void run() { 37 try { 38 URL url = new URL(path); 39 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 40 conn.setRequestMethod("GET"); 41 conn.setConnectTimeout(5000); 42 conn.setReadTimeout(5000); 43 int code = conn.getResponseCode(); 44 if (code == 200) { 45 // 得打JOSN数据,字符串 46 InputStream is = conn.getInputStream(); 47 String json = StreamTools.readStream(is).replace("__GetZoneResult_= ", ""); 48 //System.out.println(json); 49 JSONObject jsonObject = new JSONObject(); 50 final String catName = jsonObject.getString("catName"); 51 final String province = jsonObject.getString("province"); 52 showToastInAnyThread("运营商: "+catName+"\n归属地: "+province); 53 } else { 54 showToastInAnyThread("资源没有找到或者是服务器出了问题"); 55 56 } 57 } catch (Exception e) { 58 // TODO 自动生成的 catch 块 59 e.printStackTrace(); 60 showToastInAnyThread("访问失败"); 61 62 } 63 }; 64 }.start(); 65 } 66 67 public void showToastInAnyThread(final String text) { 68 runOnUiThread(new Runnable() { 69 public void run() { 70 Toast.makeText(MainActivity.this,text,0).show(); 71 }; 72 }); 73 } 74 75 76 }
最后工程的一览图:
(5)布署程序到模拟器上运行效果如下图: