android中json編碼和解碼最常用的有三種:
(1)、安卓自帶的org.json.JSONArray、JSONObject。
(2)、谷歌提供的Gson包。
(3)、阿裡巴巴的fastJson。
1、org.json中的JSONObject和JSONArray。
a、JSONObject是JSON對象的鍵值對,例如:{“name”:”bobo”, “age”:”10”}。
b、JSONArrays是JSON的數組,例如[“aa”, “bb”. {“name”:”bobo”, “age”:10}]。
c、JSONObject 和 JSONArrays隻能接收String對象,當然String對象必須是JSON結構的字元串,否則解析失敗。
d、JSONObject 和 JSONArrays對于解析接收來的json字元串比較友善,如果需要打包成json資料則比較繁瑣,建議不要使用。當然,如果接收的json字元串比較複雜,則JSONObject 和JSONArrays解析就非常複雜,這個時候采用Gson和fastJson就比較友善了。
代碼:
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", "bobo");
jsonObject.put("age", );
String strResult = jsonObject.toString();
Log.d("custom_json :", strResult);
輸出結果為:strResult = {"name":"bobo", "age":"10"};
代碼:
JSONArray jsonArray = new JSONArray();
jsonArray.put("person");
jsonArray.put("books");
jsonArray.put(jsonObject);
String arrStr = jsonArray.toString();
Log.d("custom_json :", arrStr);
輸出結果:
// [
// "person",
// "books",
// {
// "name":"bobo",
// "age":"10"
// }
// ]
2、Gson是谷歌提供的專用安卓的json第三方編碼解碼包,使用之前需要找個網站下載下傳這個jar包,然後引用自己的工程。
(1)、注解Expose、SerializedName、Unitl、Since。
a、Expose(serialize = false,deserialize = false)本注解指定哪些字段可以序 列化或反序列化,但是設定 GsonBuilder.excludeFieldsWithoutExposeAnnotation 才有用。
b、SerializedName修改字段的别名,例如SerializedName(“iD”)。
c、Unitl指定某個字段在某個版本之前可被識别,Since表示某個字段在本版本及其之後才能被識别,主要是為了版本的相容。
(2)、FieldNamingPolicy,枚舉值分别有:IDENTITY、UPPER_CAMEL_CASE、UPPER_CAMEL_CASE_WITH_SPACES、LOWER_CASE_WITH_UNDERSCORES、LOWER_CASE_WITH_DASHES。
a、FieldNamingPolicy中的幾個枚舉值,IDENTITY表示字段名不變。
b、UPPER_CAMEL_CASE:導出的字段名稱首字母變成大寫,例如:someFieldName —> SomeFieldName。
c、UPPER_CAMEL_CASE_WITH_SPACES: 将字段名的每個大寫字母開頭的用空格分開,例如:someFieldName —> Some Field Name。
d、 LOWER_CASE_WITH_UNDERSCORES:将字段每個大寫字母開頭的用下劃線(_)分開,并将分開的字元串全部轉成小寫,例如:someFieldName —> some_field_name。
e、LOWER_CASE_WITH_DASHES:将字段每個大寫字母開頭的用破折号(-)分開,并将分開的字元串全部轉成小寫,例如:someFieldName —> some-field-name。
設定的FieldNamingPolicy對于已經設定注解的SerializedName沒有影響,因為注解的優先級高于FieldNamingPolicy的設定。
(3)、TypeToken指定序列化對象的類型。
(4)、ExcludeFieldsWithoutExposeAnnotation(),對序列化的對象進行篩選,隻有注解标注有expose且serialize = true的才會被序列化,deserialize = true才會被反序列化。
(5)、enableComplexMapKeySerialization,可以對複雜的map進行序列化。
(6)、代碼測試。
代碼:
package com.example.kingsoft.ObjectLibs;
import com.example.kingsoft.CustomUtil.GsonUtil;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.google.gson.annotations.Until;
/**
* Created by qiubowang on 2017/6/7
*
* Expose(serialize = false,deserialize = false)本注解指定哪些字段可以序列化或反序列化,但是設定GsonBuilder.excludeFieldsWithoutExposeAnnotation才有用
*/
public class Person {
@Expose(serialize = true,deserialize = false)
private String mName = null;
@Expose(serialize = true)
private int mAge = -;
@Expose(serialize = false)
private String mAddress = null;
@Expose(serialize = false)
private String mSchool = null;
@SerializedName("iD")
@Expose(serialize = false)
@Until()
private String mID = null;
@GsonUtil.ICustomIgnoreAnnotation
public long mobilePhone = ;
public Person(){
}
public void setName(String name){
this.mName = name;
}
public void setAge(int age){
this.mAge = age;
}
public void setAddress(String address){
this.mAddress = address;
}
public void setSchool(String school){
this.mSchool = school;
}
public void setID(String id){
this.mID = id;
}
public String getName(){
return mName;
}
public int getAge(){
return this.mAge;
}
public String getAddress(){
return this.mAddress;
}
public String getSchool(){
return this.mAddress;
}
public String getID(){
return this.mID;
}
}
現在用以下代碼進行測試:
代碼、
Person person = new Person();
person.setName("bobo");
person.setAddress("zhuhai");
person.setAge();
person.setSchool("華中科技大學");
person.setID("123456");
mGson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.serializeNulls().setExclusionStrategies()
.enableComplexMapKeySerialization() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create();
Type typeOfT = new TypeToken<Person>(){}.getType(); /
String strPer = mGson.toJson(person, typeOfT);
輸出結果:
strPer = {"m_name":"bobo","m_age":}
Person中隻有m_name ,m_age設定了可序列化,是以經過excludeFieldsWithoutExposeAnnotation的篩選之後導出資料隻有這個屬性,因為屬性命名規則為LOWER_CASE_WITH_UNDERSCORES,是以大寫字母的以下劃線分開,并且大寫轉小寫。
(7)、自定義序列化篩選。僅僅采用excludeFieldsWithoutExposeAnnotation對序列化的屬性進行實作有時候會讓代碼特别難看,例如類中有20個屬性,如果每個屬性上都增加expse注解,則代碼看起來非常紮亂,這個時候自定義ExclusionStrategy 就派上了用場,通過實作ExclusionStrategy 的2個篩選方法,可以選擇性的去篩選掉指定的屬性或類。
一、自定義一個注解。
代碼:
/**自定義注解,注解頂層帶的注解是固定必須的(可以參考Expose結構)
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface ICustomIgnoreAnnotation{}
二、自定義排除政策。
代碼:
/**自定義排除政策
*
*/
public static class CustomExclusionStrategies implements ExclusionStrategy {
Class<?> mExClass = null;
public CustomExclusionStrategies(Class<?> exClass){
mExClass = exClass;
}
@Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
Collection<Annotation> annotations = fieldAttributes.getAnnotations();
for (Annotation annotation : annotations){
if (annotation.annotationType() == ICustomIgnoreAnnotation.class){
return true;
}
}
return false;
}
@Override
public boolean shouldSkipClass(Class<?> aClass) {
return false;
}
}
ExclusionStrategy 借口中有個方法shouldSkipField、shouldSkipClass,分别是對類和屬性進行篩選。
請檢視shouldSkipField的實作,如果傳入的屬性增加了注解ICustomIgnoreAnnotation則不對其序列化。
三、自定義注解和篩選政策已經寫好,那麼可以通過以下代碼進行引用。
Person person = new Person();
person.setName("bobo");
person.setAddress("zhuhai");
person.setAge(30);
person.setSchool("華中科技大學");
person.setID("123456");
Type typeOfT = new TypeToken<Person>(){}.getType();
CustomExclusionStrategies customExclusionStrategies = new CustomExclusionStrategies(person.getClass());
mGson = new GsonBuilder()
.setExclusionStrategies(customExclusionStrategies)
.serializeNulls().setExclusionStrategies()
.enableComplexMapKeySerialization()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create();
strPer = mGson.toJson(person, typeOfT);
輸出結果為:{"m_name":"bobo","m_age":30,"m_address":"zhuhai","m_school":"華中科技大學","iD":"123456"}
因為隻有屬性mobilePhone設定了自定義的注解ICustomIgnoreAnnotation,根據篩選政策,設定了該注解的屬性不會被序列化。
```
(8)、解JSON。
現在有一個JSON檔案如下:
{
"fillType" : "none",
"height" : ,
"shapeId" : ,
"shapeText" : {
"anchorCenter" : false,
"paraData" : [{
"className" : "c11",
"text" : "生産"
}, {
"className" : "c11",
"text" : "\n需要"
}
],
"vertical" : false
},
"width" : ,
"x" : ,
"y" :
}
現在分别采用兩種方式進行解析:
a、JSONObject、JSONArray進行解析。
//通過JSONObject,JSONArray解析
try {
JSONObject jsonObject = new JSONObject(jsonStr);
String fillType = jsonObject.getString("fillType");
int x = jsonObject.getInt("x");
int y = jsonObject.getInt("y");
double width = jsonObject.getDouble("width");
double height = jsonObject.getDouble("height");
int shapeId = jsonObject.getInt("shapeId");
JSONObject shapeText = jsonObject.getJSONObject("shapeText");
boolean anchorCenter = jsonObject.getBoolean("anchorCenter");
boolean vertical = jsonObject.getBoolean("vertical");
JSONArray paraData = jsonObject.getJSONArray("paraData");
for (int i = , length = paraData.length(); i < length; i ++){
JSONObject jsonObject1 = paraData.getJSONObject(i);
String className = jsonObject1.getString("className");
String text = jsonObject1.getString("text");
}
} catch (JSONException e) {
e.printStackTrace();
}
b、通過Gson定義Bean進行解析,定義類的屬性名稱一樣要和json檔案的key保持一模一樣。
根據以json結構,可以定義3個類,分别為ExtractDrawing、ExtractShapeText、ExtractParaData。
ExtractDrawing.java:
public class ExtractDrawing {
String fillType;
float x = ;
float y = ;
float width = ;
float height = ;
int shapeId;
ExtractShapeText shapeText = null;
public ExtractDrawing(){
shapeText = new ExtractShapeText();
}
}
ExtractShapeText.java:
public class ExtractShapeText {
boolean vertical = false;
boolean anchorCenter = false;
List<ExtractParaData> paraData = new ArrayList<>();
}
ExtractParaData.java:
public class ExtractParaData {
String className;
String text;
}
執行代碼:
//按照提供的字元串結構,自定義一些類,然後通過傳入class來進行解析
Gson gson = new Gson();
ExtractDrawing extractDrawing = gson.fromJson(jsonStr, ExtractDrawing.class);
輸出結果:
![輸出結果]:
![這裡寫圖檔描述](http://img.blog.csdn.net/?watermark//text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3FpdWJvMjAxMA==/font/a6L5L2T/fontsize//fill/I0JBQkFCMA==/dissolve//gravity/SouthEast)
3、fastJson是阿裡巴巴突出的一款開源基于JAVA的一種Json解析庫,是目前最常用JSON解析方法中最高效,也是最簡單的。fastJson已經封裝好了ExclusionStrategy ,隻需要簡單設定,可以解決大部分的功能,是以推薦首選fastJson。
(1)、fastJson預設情況下,序列化對象,則不會序列化的有一下幾種:靜态方法或者屬性,private和protected定義的屬性或者方法,setXXX(set開頭的方法),傳回值為null的不會被序列化(需要序列化需要配置SerializerFeature)。是以預設情況下,fastJson隻會序列化公有非靜态的方法或者屬性,并且set開頭的方法不會被序列化,get方法開頭的會去掉get并且get之後的第一個字母會轉成小寫, 例如:segName(){},本方法不會被序列化,getName(){},序列化的key為name。
(2)、fastJson注解,fastJson注解主要用到JSONField,本注解名字雖然是作用于屬性,其實他的目标有三個,屬性、方法及其參數,看源代碼就可以發現@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })。
本注解有ordinal(指定排列順序,預設為0),name(命名),format(格式)、serialize(是否序列化預設為true),deserialize(是否反序列化,預設true),serialzeFeatures(SerializerFeature[]),parseFeatures(Feature[])。
(3)、如果類中屬性也是公有的,本屬性的傳回方法也是有公有的,那麼如果讓序列化的對象隻保留一份,則就可以在屬性或者傳回方法寫上注解@JSONField[serialize=false].
(4)、NameFilter,ValueFilter通過key或者vale進行過濾。
(5)、SerializerFeature最常用的進行說明:
SerializerFeature.DisableCircularReferenceDetect消除對象之間的循環引用,例如 A引用了B,而B同也引用了A。
SerializerFeature.WriteMapNullValue,預設情況下如果map為null是不會序列化輸出的,如果需要輸出則配置本值,輸出值為null。
SerializerFeature.WriteNullListAsEmpty,預設情況下清單為null是不會序列化輸出的,如果需要輸出增加本配置就可以了,輸出為空。
SerializerFeature.WriteNullStringAsEmpty,預設情況下String類型的序列化屬性或者方法為null時不序列化輸出,如果需要輸出配置本值。
SerializerFeature.WriteNullNumberAsZero,如果數字類型的為null,預設情況下不序列化輸出,如果需要輸出配置本屬性會給一個預設值0。
SerializerFeature.WriteNullBooleanAsFalse,Boolean對象為null則預設不會序列化輸出,如果需要輸出配置本屬性預設給一個false。
貼上以下代碼提供參考:
public static String fastJsonEncoder(Object object){
Person person = new Person();
person.setName("bobo");
person.setAddress("zhuhai");
person.setAge();
person.setSchool("華中科技大學");
person.setID("123456");
NameFilter nameFilter = new NameFilter() {
Pattern pattern = Pattern.compile("[0-9]*");
//正規表達式判定定ke是否為數字
public boolean isIndex(String str) {
Matcher isNum = pattern.matcher(str);
return isNum.matches();
}
/**
*
* @param o
* @param propertyName
* @param propertyValue
* @return 擷取到的為key,如果要修改key的值,則在process處理後傳回的就是修改之後的key的值
*/
@Override
public String process(Object o, String propertyName, Object propertyValue) {
//propertyName,序列化後的每個key,propertyValue序列化後的每個key的value
return propertyName;
}
};
ValueFilter valueFilter = new ValueFilter() {
/**
*
* @param o
* @param propertyName
* @param propertyValue
* @return 傳回的是修改後的value的值,如果需要修改某個key對應的value的值,則在processc處理之後傳回的值即是修改的value的值
*/
@Override
public Object process(Object o, String propertyName, Object propertyValue) {
//propertyName,序列化後的每個key,propertyValue序列化後的每個key的value
if (propertyName.equals("bobo"))
return new String("13633333333");
else
return null;
}
};
return JSON.toJSONString(person, nameFilter, SerializerFeature.DisableCircularReferenceDetect);
}