Android中解析JSON

来源:互联网 发布:我的小公主 知乎 编辑:程序博客网 时间:2024/04/28 17:28

JSON简介

JSON 语法规则

JSON 语法是 JavaScript 对象表示法语法的子集。

  • 数据在名称/值对中
  • 数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组

JSON 名称/值对

JSON 数据的书写格式是:名称/值对。

名称/值对包括字段名称(在双引号中),后面写一个冒号,然后是值:

"firstName" : "John"

这很容易理解,等价于这条 JavaScript 语句:

firstName = "John"

JSON 值

JSON 值可以是:

  • 数字(整数或浮点数)
  • 字符串(在双引号中)
  • 逻辑值(true 或 false)
  • 数组(在方括号中)
  • 对象(在花括号中)
  • null

JSON 对象

JSON 对象在花括号中书写:

对象可以包含多个名称/值对:

{ "firstName":"John" , "lastName":"Doe" }

这一点也容易理解,与这条 JavaScript 语句等价:

firstName = "John"lastName = "Doe"

JSON 数组

JSON 数组在方括号中书写:

数组可包含多个对象:

{"employees": [{ "firstName":"John" , "lastName":"Doe" },{ "firstName":"Anna" , "lastName":"Smith" },{ "firstName":"Peter" , "lastName":"Jones" }]}

在上面的例子中,对象 "employees" 是包含三个对象的数组。每个对象代表一条关于某人(有姓和名)的记录。

JSON 使用 JavaScript 语法

因为 JSON 使用 JavaScript 语法,所以无需额外的软件就能处理 JavaScript 中的 JSON。

通过 JavaScript,您可以创建一个对象数组,并像这样进行赋值:

例子

var employees = [{ "firstName":"Bill" , "lastName":"Gates" },{ "firstName":"George" , "lastName":"Bush" },{ "firstName":"Thomas" , "lastName": "Carter" }];

可以像这样访问 JavaScript 对象数组中的第一项:

employees[0].lastName;

返回的内容是:

Gates

可以像这样修改数据:

employees[0].lastName = "Jobs";

在下面的章节,您将学到如何把 JSON 文本转换为 JavaScript 对象。

JSON 文件

  • JSON 文件的文件类型是 ".json"
  • JSON 文本的 MIME 类型是 "application/json"

JSON解析常用类

1. Android JSON所有相关类,都在org.json包下

JSONObject、JSONArray、JSONException、JSONStringer、JSONTokener

2. 常见方法
使用get方法与使用opt方法的区别?
JsonObject 方法,opt* 与 get* 建议使用opt方法,因为get方法如果其内容为空会直接抛出异常。不过JsonArray.opt*(index)会有越界问题需要特别注意。
[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. opt、optBoolean、optDouble、optInt、optLong、optString、optJSONArray、optJSONObject  
  2. get、getBoolean、getDouble、getInt、getLong、getString、getJSONArray、getJSONObject  
3. Android创建JSON
[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. private String createJson() throws JSONException {  
  2.  JSONObject jsonObject = new JSONObject();  
  3.  jsonObject.put ("intKey" , 123);  
  4.  jsonObject.put ("doubleKey" , 10.1);  
  5.  jsonObject.put ("longKey" , 666666666);  
  6.  jsonObject.put ("stringKey" , "lalala" );  
  7.  jsonObject.put ("booleanKey" , true);  
  8.    
  9.  JSONArray jsonArray = new JSONArray();  
  10.  jsonArray.put (0111);  
  11.  jsonArray.put("second");  
  12.  jsonObject.put ("arrayKey" , jsonArray);  
  13.    
  14.  JSONObject innerJsonObject = new JSONObject();  
  15.  innerJsonObject.put ("innerStr" , "inner" );  
  16.  jsonObject.put ("innerObjectKey" , innerJsonObject);  
  17.    
  18.    
  19.  Log.e("Json" , jsonObject.toString());  
  20.    
  21.  return jsonObject.toString();  
  22.  }  
输出结果:
{"intKey":123, "doubleKey":10.1, "longKey":666666666, "stringKey":"lalala", "booleanKey":true, "arrayKey":[111,"second"], "innerObjectKey":{"innerStr":"inner"}}
4. 解析上面创建的JSON
[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. private void pareJson(String jsonStr) throws JSONException {  
  2.  JSONObject jsonObject = new JSONObject(jsonStr);  
  3.  int intValue       = jsonObject.optInt( "intKey");  
  4.  double doubleValue = jsonObject.optDouble( "doubleKey");  
  5.  long longValue     = jsonObject.optLong( "longKey");  
  6.  String strValue    = jsonObject.optString( "stringKey");  
  7.  boolean boolValue  = jsonObject.optBoolean( "booleanKey");  
  8.    
  9.  JSONArray array    = jsonObject.optJSONArray( "arrayKey");  
  10.  int arrIntValue    = array.optInt(0);  
  11.  String arrStrValue = array.optString(1);  
  12.    
  13.  JSONObject innerJson = jsonObject.optJSONObject("innerObjectKey" );  
  14.  String innerStr      = innerJson.optString( "innerStr");  
  15.    
  16.  Log.e("Json" , "intValue = " + intValue + " , doubleValue = " + doubleValue  
  17.             + " , longValue = " + longValue + " , strValue = " + strValue  
  18.             + " , booleanValue = " + boolValue + " , arrIntValue = " + arrIntValue  
  19.             + " , arrStrValue = " + arrStrValue + " , innerStr = " + innerStr);  
  20. }  
输出结果:
intValue = 123 , doubleValue = 10.1 , longValue = 666666666 , strValue = lalala , booleanValue = true , arrIntValue = 111 , arrStrValue = second , innerStr = inner
更加详细的解析请参考《android json解析及简单例子》:http://blog.csdn.net/lwwgtm/article/details/8990019

android的json解析部分都在包org.json下,主要有以下几个类: 

JSONObject:可以看作是一个json对象,这是系统中有关JSON定义的基本单元,其包含一对儿(Key/Value)数值。它对外部(External:   应用toString()方法输出的数值)调用的响应体现为一个标准的字符串(例如:{"JSON": "Hello, World"},最外被大括号包裹,其中的KeyValue被冒号":"分隔)。其对于内部(Internal)行为的操作格式略微,例如:初始化一个JSONObject实例,引用内部的put()方法添加数值:new JSONObject().put("JSON", "Hello, World!"),在KeyValue之间是以逗号","分隔。Value的类型包括:BooleanJSONArrayJSONObjectNumberString或者默认值JSONObject.NULL object 。

JSONStringer:json文本构建类 ,根据官方的解释,这个类可以帮助快速和便捷的创建JSON text。其最大的优点在于可以减少由于 格式的错误导致程序异常,引用这个类可以自动严格按照JSON语法规则(syntax rules)创建JSON text。每个JSONStringer实体只能对应创建一个JSON text。。其最大的优点在于可以减少由于格式的错误导致程序异常,引用这个类可以自动严格按照JSON语法规则(syntax rules)创建JSON text。每个JSONStringer实体只能对应创建一个JSON text。

JSONArray它代表一组有序的数值。将其转换为String输出(toString)所表现的形式是用方括号包裹,数值以逗号”,”分隔(例如:     [value1,value2,value3],大家可以亲自利用简短的代码更加直观的了解其格式)。这个类的内部同样具有查询行为,     get()和opt()两种方法都可以通过index索引返回指定的数值,put()方法用来添加或者替换数值。同样这个类的value类型可以包括:Boolean、JSONArray、JSONObject、Number、String或者默认值JSONObject.NULL object。

JSONTokener:json解析类 
JSONException:json中用到的异常 

除了上面的JSONObject和JSONArray,还可以使用JSONStringer来构建json文本 

Java代码  
  1. try {  
  2.     JSONStringer jsonText = new JSONStringer();  
  3.     // 首先是{,对象开始。object和endObject必须配对使用  
  4.     jsonText.object();  
  5.       
  6.     jsonText.key("phone");  
  7.     // 键phone的值是数组。array和endArray必须配对使用  
  8.     jsonText.array();  
  9.     jsonText.value("12345678").value("87654321");  
  10.     jsonText.endArray();  
  11.       
  12.     jsonText.key("name");  
  13.     jsonText.value("yuanzhifei89");  
  14.     jsonText.key("age");  
  15.     jsonText.value(100);  
  16.       
  17.     jsonText.key("address");  
  18.     // 键address的值是对象  
  19.     jsonText.object();  
  20.     jsonText.key("country");  
  21.     jsonText.value("china");  
  22.     jsonText.key("province");  
  23.     jsonText.value("jiangsu");  
  24.     jsonText.endObject();  
  25.       
  26.     jsonText.key("married");  
  27.     jsonText.value(false);  
  28.       
  29.     // },对象结束  
  30.     jsonText.endObject();  
  31. catch (JSONException ex) {  
  32.     throw new RuntimeException(ex);  
  33. }  


json文本解析类JSONTokener  
按照RFC4627规范将json文本解析为相应的对象。  


对于将json文本解析为对象,只需要用到该类的两个api: 
构造函数 
public Object nextValue(); 

代码  
  1. //  {  
  2. //      "phone" : ["12345678", "87654321"], // 数组  
  3. //      "name" : "yuanzhifei89", // 字符串  
  4. //      "age" : 100, // 数值  
  5. //      "address" : { "country" : "china", "province" : "jiangsu" }, // 对象  
  6. //      "married" : false // 布尔值  
  7. //  }  
  8.   
  9.   final String JSON = "{'phone':['12345678','87654321']," +    "'name':'yuanzhifei89'," +    "'age':100," +    "'address':{'country':'china','province':'jiangsu'}," +    "'married': false}";

  1.   
  2. try {  
  3.     JSONTokener jsonParser = new JSONTokener(JSON);  
  4.     // 此时还未读取任何json文本,直接读取就是一个JSONObject对象。  
  5.     // 如果此时的读取位置在"name" : 了,那么nextValue就是"yuanzhifei89"(String)  
  6.     JSONObject person = (JSONObject) jsonParser.nextValue();  
  7.     // 接下来的就是JSON对象的操作了  
  8.     person.getJSONArray("phone");  
  9.     person.getString("name");  
  10.     person.getInt("age");  
  11.     person.getJSONObject("address");  
  12.     person.getBoolean("married");  
  13. catch (JSONException ex) {  
  14.     // 异常处理代码  
  15. }  

 

其它的api基本就是用来查看json文本中的文本的 

代码  
  1. try {  
  2.     JSONTokener jsonParser = new JSONTokener(JSON);  
  3.     // 继续向下读8个json文本中的字符。此时刚开始,即在{处  
  4.     jsonParser.next(8); //{    "phone。tab算一个字符  
  5.       
  6.     // 继续向下读1个json文本中的字符  
  7.     jsonParser.next(); //"  
  8.       
  9.     // 继续向下读取一个json文本中的字符。该字符不是空白、同时也不是注视中的字符  
  10.     jsonParser.nextClean(); //:  
  11.       
  12.     // 返回当前的读取位置到第一次遇到'a'之间的字符串(不包括a)。  
  13.     jsonParser.nextString('a'); //  ["12345678", "87654321"],    "n(前面有两个空格)  
  14.       
  15.     // 返回当前读取位置到第一次遇到字符串中(如"0089")任意字符之间的字符串,同时该字符是trimmed的。(此处就是第一次遇到了89)  
  16.     jsonParser.nextTo("0089"); //me" : "yuanzhifei  
  17.       
  18.     // 读取位置撤销一个  
  19.     jsonParser.back();  
  20.     jsonParser.next(); //i  
  21.       
  22.     // 读取位置前进到指定字符串处(包括字符串)  
  23.     jsonParser.skipPast("address");  
  24.     jsonParser.next(8); //" : { "c  
  25.       
  26.     // 读取位置前进到执行字符处(不包括字符)  
  27.     jsonParser.skipTo('m');  
  28.     jsonParser.next(8); //married"  
  29. catch (JSONException ex) {  
  30.     // 异常处理代码  
  31. }  

例子:

gson(http://code.google.com/p/google-gson/)

下面我们来看看Google提供的gson这个json解析库,同样我们需要去下载gson这个jar包,导入到我们的项目中

使用gson,我们可以非常轻松的实现数据对象和json对象的相互转化,其中我们最常用的就是两个方法,一个是fromJSON(),将json对象转换成我们需要的数据对象,另一个是toJSON(),这个就是将我们的数据对象转换成json对象。下面我们也通过一个综合的例子来看看gson的使用方法:

复制代码
public class JsonService{    public Person getPerson()    {        Person person = new Person(1, "xiaoluo", "广州");        return person;    }        public List<Person> getPersons()    {        List<Person> persons = new ArrayList<Person>();        Person person = new Person(1, "xiaoluo", "广州");        Person person2 = new Person(2, "android", "上海");        persons.add(person);        persons.add(person2);        return persons;    }        public List<String> getString()    {        List<String> list = new ArrayList<String>();        list.add("广州");        list.add("上海");        list.add("北京");        return list;    }        public List<Map<String, String>> getMapList()    {        List<Map<String, String>> list = new ArrayList<Map<String, String>>();        Map<String, String> map1 = new HashMap<String, String>();        map1.put("id", "001");        map1.put("name", "xiaoluo");        map1.put("age", "20");        Map<String, String> map2 = new HashMap<String, String>();        map2.put("id", "002");        map2.put("name", "android");        map2.put("age", "33");        list.add(map1);        list.add(map2);        return list;    }}
复制代码
复制代码
public static void main(String[] args)    {        Gson gson = new Gson();        JsonService jsonService = new JsonService();        Person person = jsonService.getPerson();        System.out.println("person: " + gson.toJson(person));        //    对于Object类型,使用 fromJson(String, Class)方法来将Json对象转换成Java对象        Person person2 = gson.fromJson(gson.toJson(person), Person.class);        System.out.println(person2);        System.out.println("------------------------------------------------");                List<Person> persons = jsonService.getPersons();        System.out.println("persons: " + gson.toJson(persons));        /*         * 对于泛型对象,使用fromJson(String, Type)方法来将Json对象转换成对应的泛型对象         * new TypeToken<>(){}.getType()方法         */        List<Person> persons2 = gson.fromJson(gson.toJson(persons), new TypeToken<List<Person>>(){}.getType());        System.out.println(persons2);        System.out.println("------------------------------------------------");                List<String> list = jsonService.getString();        System.out.println("String---->" + gson.toJson(list));        List<String> list2 = gson.fromJson(gson.toJson(list), new TypeToken<List<String>>(){}.getType());        System.out.println("list2---->" + list2);        System.out.println("------------------------------------------------");                List<Map<String, String>> listMap = jsonService.getMapList();        System.out.println("Map---->" + gson.toJson(listMap));        List<Map<String, String>> listMap2 = gson.fromJson(gson.toJson(listMap), new TypeToken<List<Map<String, String>>>(){}.getType());        System.out.println("listMap2---->" + listMap2);        System.out.println("------------------------------------------------");    }
复制代码

看看控制台的输出:

复制代码
person: {"id":1,"name":"xiaoluo","address":"广州"}Person [id=1, name=xiaoluo, address=广州]------------------------------------------------persons: [{"id":1,"name":"xiaoluo","address":"广州"},{"id":2,"name":"android","address":"上海"}][Person [id=1, name=xiaoluo, address=广州], Person [id=2, name=android, address=上海]]------------------------------------------------String---->["广州","上海","北京"]list2---->[广州, 上海, 北京]------------------------------------------------Map---->[{"id":"001","age":"20","name":"xiaoluo"},{"id":"002","age":"33","name":"android"}]listMap2---->[{id=001, age=20, name=xiaoluo}, {id=002, age=33, name=android}]------------------------------------------------
复制代码

三、在Android客户端解析服务器端的json数据

下面我们来完成一个综合的例子,Android客户端通过一个AsyncTask异步任务请求服务器端的某些数据,然后在解析完这些数据后,将得到的数据内容更新到我们的Spinner这个UI控件当中。

我们首先来看下服务器端的代码:

复制代码
@WebServlet("/CityServlet")public class CityServlet extends HttpServlet{    private static final long serialVersionUID = 1L;    public CityServlet()    {        super();    }    protected void doGet(HttpServletRequest request,            HttpServletResponse response) throws ServletException, IOException    {        this.doPost(request, response);    }    protected void doPost(HttpServletRequest request,            HttpServletResponse response) throws ServletException, IOException    {        response.setContentType("text/html;charset=utf-8");        request.setCharacterEncoding("utf-8");        response.setCharacterEncoding("utf-8");        PrintWriter writer = response.getWriter();                String type = request.getParameter("type");        if("json".equals(type))        {            List<String> cities = new ArrayList<String>();            cities.add("广州");            cities.add("上海");            cities.add("北京");            cities.add("湖南");            Map<String, List<String>> map = new HashMap<String, List<String>>();            map.put("cities", cities);            String citiesString = JSON.toJSONString(map);            writer.println(citiesString);        }                writer.flush();        writer.close();    }}
复制代码

如果客户端请求的参数是type=json,则响应给客户端一个json数据格式

接着来看看客户端的代码,首先看看客户端的布局文件,其实就是一个按钮和一个Spinner控件,当点击按钮后,通过http协议请求服务器端的数据,然后在接收到后再更新我们的Spinner控件的数据

复制代码
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <TextView        android:id="@+id/textView1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentLeft="true"        android:layout_alignParentTop="true"        android:layout_marginLeft="64dp"        android:layout_marginTop="64dp"        android:textSize="20sp"        android:text="城市" />        <Spinner         android:id="@+id/spinner"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignTop="@id/textView1"        android:layout_toRightOf="@id/textView1"/>    <Button        android:id="@+id/button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignLeft="@+id/textView1"        android:layout_below="@+id/spinner"        android:layout_marginLeft="22dp"        android:layout_marginTop="130dp"        android:text="加载数据" /></RelativeLayout>
复制代码

在Android客户端写一个解析json数据格式的类:

复制代码
public class JsonUtils{    /**     * @param citiesString    从服务器端得到的JSON字符串数据     * @return    解析JSON字符串数据,放入List当中     */    public static List<String> parseCities(String citiesString)    {        List<String> cities = new ArrayList<String>();                try        {            JSONObject jsonObject = new JSONObject(citiesString);            JSONArray jsonArray = jsonObject.getJSONArray("cities");            for(int i = 0; i < jsonArray.length(); i++)            {                cities.add(jsonArray.getString(i));            }        }        catch (Exception e)        {            e.printStackTrace();        }                return cities;    }}
复制代码

当然我们的HttpUtils类也不可少:

复制代码
public class HttpUtils{    /**     * @param path    请求的服务器URL地址     * @param encode    编码格式     * @return    将服务器端返回的数据转换成String     */    public static String sendPostMessage(String path, String encode)    {        String result = "";        HttpClient httpClient = new DefaultHttpClient();        try        {            HttpPost httpPost = new HttpPost(path);            HttpResponse httpResponse = httpClient.execute(httpPost);            if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)            {                HttpEntity httpEntity = httpResponse.getEntity();                if(httpEntity != null)                {                    result = EntityUtils.toString(httpEntity, encode);                }            }        }        catch (Exception e)        {            e.printStackTrace();        }        finally        {            httpClient.getConnectionManager().shutdown();        }                return result;    }}
复制代码

最后来看看我们的MainActivity类:

复制代码
public class MainActivity extends Activity{    private Spinner spinner;    private Button button;    private ArrayAdapter<String> adapter;    private ProgressDialog dialog;    private final String CITY_PATH_JSON = "http://172.25.152.34:8080/httptest/CityServlet?type=json";    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                spinner = (Spinner)findViewById(R.id.spinner);        button = (Button)findViewById(R.id.button);        dialog = new ProgressDialog(MainActivity.this);        button.setOnClickListener(new OnClickListener()        {            @Override            public void onClick(View v)            {                dialog.setTitle("提示信息");                dialog.setMessage("loading......");                dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);                dialog.setCancelable(false);                                new MyAsyncTask().execute(CITY_PATH_JSON);            }        });    }    public class MyAsyncTask extends AsyncTask<String, Void, List<String>>    {        @Override        protected void onPreExecute()        {            dialog.show();        }        @Override        protected List<String> doInBackground(String... params)        {            List<String> cities = new ArrayList<String>();            String citiesString = HttpUtils.sendPostMessage(params[0], "utf-8");            //    解析服务器端的json数据            cities = JsonUtils.parseCities(citiesString);return cities;        }        @Override        protected void onPostExecute(List<String> result)        {            adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_spinner_item, result);            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);            spinner.setAdapter(adapter);            dialog.dismiss();        }    }        @Override    public boolean onCreateOptionsMenu(Menu menu)    {        getMenuInflater().inflate(R.menu.main, menu);        return true;    }}
复制代码

当然别往了开启我们的网络授权

<uses-permission android:name="android.permission.INTERNET"/>

最后我们来看看效果图:

这样我们就完成了客户端与服务器端通过json来进行数据的交换

 

总结:本篇随笔主要讲解了JSON这种轻量级的数据交换格式的概念,以及讲解了两种解析json数据的解析类(json-lib以及gson),最后通过一个小例子实现了在Android客户端和服务器端使用json这种数据格式来进行数据的交换。


Android 读取app内json配置文件


public class AppJsonFileReader {
public static String getJson(Context context, String fileName) {

StringBuilder stringBuilder = new StringBuilder();
try {
AssetManager assetManager = context.getAssets();
BufferedReader bf = new BufferedReader(new InputStreamReader(
assetManager.open(fileName)));
String line;
while ((line = bf.readLine()) != null) {
stringBuilder.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return stringBuilder.toString();
}

public static List<Map<String, String>> setData(String str) {
try {
List<Map<String, String>> data = new ArrayList<Map<String, String>>();
JSONArray array = new JSONArray(str);
int len = array.length();
Map<String, String> map;
for (int i = 0; i < len; i++) {
JSONObject object = array.getJSONObject(i);
map = new HashMap<String, String>();
map.put("operator", object.getString("operator"));
map.put("loginDate", object.getString("loginDate"));
map.put("logoutDate", object.getString("logoutDate"));
data.add(map);
}
return data;
} catch (JSONException e) {
e.printStackTrace();
return null;
}

}

public static List<Map<String, String>> setListData(String str) {
List<Map<String, String>> data = new ArrayList<Map<String, String>>();
try {

JSONArray array = new JSONArray(str);
int len = array.length();
Map<String, String> map;
for (int i = 0; i < len; i++) {
JSONObject object = array.getJSONObject(i);
map = new HashMap<String, String>();
map.put("imageId", object.getString("imageId"));
map.put("title", object.getString("title"));
map.put("subTitle", object.getString("subTitle"));
map.put("type", object.getString("type"));
data.add(map);
}

} catch (JSONException e) {
e.printStackTrace();
}
return data;

}
}






0 0
原创粉丝点击