1. 程式人生 > >Android okHttp網路請求之Json解析

Android okHttp網路請求之Json解析

  前言:

  前面兩篇文章介紹了基於okHttp的post、get請求,以及檔案的上傳下載,今天主要介紹一下如何和Json解析一起使用?如何才能提高開發效率?

     okHttp相關文章地址:

 關於Json解析:

  本文的Json解析採用阿里巴巴的FastJson 解析,也可以採用Gson解析,兩者之間的對比請參考文章Android之json解析(FastJson Gson 對比)(http://www.cnblogs.com/whoislcj/p/5468420.html)。

 關於泛型:

  本文將採用json統一泛型解析,閱讀本文之前請先對java泛型知識有一定的瞭解。

 關於反射機制:

 本文會採用Java的反射機制來解析泛型物件Class<?>,閱讀本文之前請先對Java發射機制知識有一定的瞭解。

程式碼實現:

1.)首先我們宣告一個TypeInfo.java類用來封裝泛型相關屬性
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class TypeInfo {
    //Type泛型物件型別
private Class<?> componentType; //Type所屬物件型別 private Class<?> rawType; //type private Type type; private TypeInfo(Class<?> rawType, Class<?> componentType) { this.componentType = componentType; this.rawType = rawType; }
public static TypeInfo createArrayType(Class<?> componentType) { return new TypeInfo(Array.class, componentType); } public static TypeInfo createNormalType(Class<?> componentType) { return new TypeInfo(null, componentType); } public static TypeInfo createParameterizedType(Class<?> rawType, Class<?> componentType) { return new TypeInfo(rawType, componentType); } public TypeInfo(Type type) { this.type = type; if (type instanceof ParameterizedType) { //返回 Type 物件,表示宣告此型別的類或介面。 this.rawType = (Class<?>) ((ParameterizedType) type).getRawType(); //getActualTypeArguments()返回表示此型別實際型別引數的 Type 物件的陣列。 Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments(); this.componentType = (Class<?>) actualTypeArguments[0]; // typeReference=new TypeReference<Map<componentType,componentType>>(){}; } else if (type instanceof GenericArrayType) { //返回 Type 物件,表示宣告此型別的類或介面。 this.rawType = Array.class; // 表示一種元素型別是引數化型別或者型別變數的陣列型別 this.componentType = (Class<?>) ((GenericArrayType) type).getGenericComponentType(); } else { this.componentType = (Class<?>) type; } } public Type getType() { return type; } public Class<?> getComponentType() { return componentType; } public Class<?> getRawType() { return rawType; } }
2.)宣告ReqClassUtils.java類 用於通過反射機制獲取泛型物件的TypeInfo
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class ReqClassUtils {

    public static TypeInfo getCallbackGenericType(Class<?> clazz) {
        //獲得帶有泛型的父類
        Type genericSuperclass = clazz.getGenericSuperclass();//Type是 Java 程式語言中所有型別的公共高階介面。它們包括原始型別、引數化型別、陣列型別、型別變數和基本型別。
        TypeInfo type = getGetnericType(genericSuperclass);
        if (type == null) {
            Type[] genericInterfaces = clazz.getGenericInterfaces();
            if (genericInterfaces != null && genericInterfaces.length > 0) {
                type = getGetnericType(genericInterfaces[0]);
            }
        }
        return type;
    }

    private static TypeInfo getGetnericType(Type type) {
        if (type != null && type instanceof ParameterizedType) {
            //getActualTypeArguments獲取引數化型別的陣列,泛型可能有多個
            Type[] args = ((ParameterizedType) type).getActualTypeArguments();
            if (args != null && args.length > 0) {
                return new TypeInfo(args[0]);
            }
        }
        return null;
    }
}
3.)接下來重點來了,宣告一個json解析工具類ReqJsonUtils.java,主要用於通過TypeInfo相關屬性進行不同型別的json解析
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import static com.alibaba.fastjson.JSON.parseObject;

public class ReqJsonUtils {

    //基本型別對映關係Map
    private static final Map primitiveWrapperTypeMap = new HashMap(8);

    static {
        //新增基本型別
        primitiveWrapperTypeMap.put(Boolean.class, boolean.class);
        primitiveWrapperTypeMap.put(Byte.class, byte.class);
        primitiveWrapperTypeMap.put(Character.class, char.class);
        primitiveWrapperTypeMap.put(Double.class, double.class);
        primitiveWrapperTypeMap.put(Float.class, float.class);
        primitiveWrapperTypeMap.put(Integer.class, int.class);
        primitiveWrapperTypeMap.put(Long.class, long.class);
        primitiveWrapperTypeMap.put(Short.class, short.class);
    }

    /**
     * 將JSON字串轉換成指定的使用者返回值型別
     *
     * @param type
     * @param jsonData
     * @return
     * @throws JSONException
     */
    public static <T> T parseHttpResult(TypeInfo type, String jsonData) throws JSONException {
        // 處理Void型別的返回值
        if (Void.class.isAssignableFrom(type.getComponentType())) {
            return null;
        }
        //獲取當前type的資料型別
        Class<?> rawType = type.getRawType();
        //是否是Array
        boolean isArray = rawType != null && Array.class.isAssignableFrom(rawType);
        //是否是Collection
        boolean isCollection = rawType != null && Collection.class.isAssignableFrom(rawType);
        //是否是Map
        boolean isMap = rawType != null && Map.class.isAssignableFrom(rawType);
        //獲取泛型型別
        Class<?> componentType = type.getComponentType();
        //宣告結果物件
        T result = null;
        if (isCollection) {//處理collection
            result = (T) JSON.parseArray(jsonData, componentType);
        } else if (isArray) {//處理array
            result = (T) JSON.parseArray(jsonData, componentType).toArray();
        } else if (isMap) {//處理Map
            result = (T) JSONObject.parseObject(jsonData, type.getType());
        } else if (componentType.isAssignableFrom(String.class)) {//處理字串返回值
            return (T) jsonData;
        } else {
            // 介面的返回型別如果是簡單型別,則會封裝成為一個json物件,真正的物件儲存在value屬性上
            if (isPrimitiveOrWrapper(componentType)) {
                result = (T) parseObject(jsonData);
            } else {
                //處理自定義物件
                result = (T) parseObject(jsonData, componentType);
            }
        }
        return result;
    }

    /**
     * 判斷是否是基本資料型別
     *
     * @param clazz
     * @return
     */
    public static boolean isPrimitiveOrWrapper(Class clazz) {
        return (clazz.isPrimitive() || isPrimitiveWrapper(clazz));
    }

    /**
     * 判斷是否是基本資料型別
     *
     * @param clazz
     * @return
     */
    public static boolean isPrimitiveWrapper(Class clazz) {
        return primitiveWrapperTypeMap.containsKey(clazz);
    }
}

如何使用?

1.)實現解析
 TypeInfo typeInfo = ReqClassUtils.getCallbackGenericType(callBack.getClass());
 callBack.onReqSuccess(ReqJsonUtils.parseHttpResult(typeInfo, jsonData));
2.)傳送請求
        HashMap<String, String> paramsMap = new HashMap<>();
        paramsMap.put("sourceType", "2");
        paramsMap.put("sourceDesc", "[Android]" + Build.VERSION.RELEASE + "[Mobel]" + Build.BRAND + " " + Build.MODEL + Build.DEVICE);
        HashMap<String, String> params = dealStringBody(paramsMap);
        RequestManager.getInstance(this).requestAsyn("xxx/actionUrl", RequestManager.TYPE_POST_JSON, params, new ReqCallBack<String>() {

            @Override
            public void onReqSuccess(String result) {
                request_tv.setText(result);
            }

            @Override
            public void onReqFailed(String errorMsg) {

            }
        });
3.)支援型別
        new ReqCallBack<List<Object>>();//集合collection
        new ReqCallBack<Map<String, User>>();//map
        new ReqCallBack<Void>();//Void
        new ReqCallBack<Long>();//基礎型別

小結:如此一來發送請求到解析資料變得So easy !用流行的一句廣告語來說的話,那就是老闆再也不用擔心我搞不定網路請求和json解析了。

相關推薦

Android okHttp網路請求Json解析

  前言:   前面兩篇文章介紹了基於okHttp的post、get請求,以及檔案的上傳下載,今天主要介紹一下如何和Json解析一起使用?如何才能提高開發效率?      okHttp相關文章地址:  關於Json解析:   本文的Json解析採用阿里巴巴的FastJson 解析,也可以採用Gso

Android okHttp網路請求快取控制Cache-Control

前言:     前面的學習基本上已經可以完成開發需求了,但是在專案中有時會遇到對請求做個快取,當沒網路的時候優先載入本地快取,基於這個需求我們來學習一直okHttp的Cache-Control。      okHttp相關文章地址: Cache-Control:      Cache-Contro

Android okHttp網路請求Retrofit+Okhttp+RxJava組合

前言:     通過上面的學習,我們不難發現單純使用okHttp來作為網路庫還是多多少少有那麼一點點不太方便,而且還需自己來管理介面,對於介面的使用的是哪種請求方式也不能一目瞭然,出於這個目的接下來學習一下Retrofit+Okhttp的搭配使用。      okHttp相關文章地址: Retrof

Android okHttp網路請求檔案上傳下載

前言:    前面介紹了基於okHttp的get、post基本使用(http://www.cnblogs.com/whoislcj/p/5526431.html),今天來實現一下基於okHttp的檔案上傳、下載。      okHttp相關文章地址: 檔案上傳: 1.)不帶引數上傳檔案

Android okHttp網路請求Get/Post請求

   前言:       之前專案中一直使用的Xutils開源框架,從xutils 2.1.5版本使用到最近的xutils 3.0,使用起來也是蠻方便的,只不過最近想著完善一下app中使用的開源框架,由於Xutils裡面包含的東西相對來說比較雜,有資料庫、圖片快取、註解、網路請求等等,秉著一個開源庫只處理一

Android 網路開發(一) okHttp網路請求快取控制Cache-Control

Cache-Control: Cache-Control指定請求和響應遵循的快取機制。在請求訊息或響應訊息中設定Cache-Control並不會修改另一個訊息處理過程中的快取處理過程。請求時的快取指令有下幾種: Public指示響應可被任何快取區快取。 Private指示對於單個

Android----------OkHttp網路請求框架Get和Post簡單封裝(泛型)

請求框架的類: OkHttp依賴: compile 'com.squareup.okhttp3:okhttp:3.8.1' RecyclerView依賴: compile 'com.android.support:recyclerview-v7:26.0.0-alpha1

Flutter網路請求JSON解析

本文介紹如何在Flutter中建立HTTP網路請求和對請求的json string進行型別解析. 網路請求 官方使用的是用dart io中的HttpClient發起的請求,但HttpClient本身功能較弱,很多常用功能都不支援。 建議使用dio 來發起網路請求,它是一個強大易用的dart http請求庫

iOS 自己封裝的網路請求json解析的類

基本上所有的APP都會涉及網路這塊,不管是用AFNetWorking還是自己寫的http請求,整個網路框架的搭建很重要。 樓主封裝的網路請求類,包括自己寫的http請求和AFNetWorking的請求,程式碼簡單,主要是框架搭建。簡單來說,就是一個請求類,一個

Android網路請求OkHttp框架

首先宣告許可權 <uses-permission android:name="android.permission.INTERNET"/> 在build.gradle中加入 compile 'com.squareup.okhttp:okhttp:2.4.0' compile

Android 網路獲取資料Json解析

1.簡介 JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。 JSON資料作為目前網路中主流的資料傳輸格式之一,應用十分廣泛。 2. Json資料格式(兩種) Json資料有兩種格式: (1)物件 :物件表示

Android訪問網路系列--服務端返回XML或JSON格式資料,Android 進行解析並顯示

例子說明:使用者通過訪問web資源的最新電影資訊,伺服器端生成XML或JSON格式資料,返回Android客戶端進行顯示。 此案例開發需要兩個方面 WEB開發和android開發. 一.web開發相對比較簡單,只是模擬一下 相關程式碼如下: 1.實體Bean package ygc.yxb.domain

[python筆記]python腳本常用json解析,發送url請求,時間

結果 base () ron import add ret python3 2.7 python 2.7 json解析: import json def parse_to_str(parsed_json): return json.dumps(parsed_json

androidJSON解析

Json解析 JavaScrip物件表示法(JavaScript Object Notation)JSON屬於輕量級文字資料交換格式 JSon獨立於平臺和語言JSON具有自我描述性更易於理解 類似Xml,比Xml更小,更快,更易解析 Json檔案

Android 網路請求Xutils環境搭建

Xutils 在Android 開發中是一個比較老的網路請求框架,目前在市面上,仍然有一些老的專案在使用和維護. 本文給需要使用Xutils網路請求框架的朋友,提供一個快速搭建的程式碼參考: app的module build,gradle中 新增: compile 'org.xuti

解決利用Okhttp+Retrofit 傳送網路請求得到json是unicode

我們在用Okhttp和Retrofit傳送網路請求時,得到的json中漢子是unicode編碼,如圖 此時我們需要在Okhttp初始化的時候設定它的網路編輯器,同時將返回值的編碼改成UTF-8. 之前設定的OKhttp HttpLoggingInte

androidokhttp post請求傳遞json資料

public final static int CONNECT_TIMEOUT = 60; public final static int READ_TIMEOUT = 100;

Android專案JSON解析(3種解析技術詳解)

前言: 在我寫部落格前再宣告一下,我希望轉載我文章的某某某記得註明:(),要尊重我的勞動成果,這樣才能給我更多的支援和鼓勵!差不多有3天沒有寫部落格了,要想的、要做的事情太多了,額....原歸正傳,今天接著上一篇部落格:Android專案之JSON解析(扯淡),繼續分享我對

Android總結json解析(FastJson Gson 對比)

前言: 最近為了統一專案中使用的框架,發現專案中用到了兩種json解析框架,他們就是當今非常主流的json解析框架:google的Gson 和阿里巴巴的FastJson,為了廢除其中一個所以來個效能和使用的大比拼。 FastJson簡介:Fastjson是一個Java語言編寫的JSON處理器,由阿里巴巴公

AndroidOkHttp 網路請求框架的學習封裝

自述:在此以前,自己從來沒有寫過部落格,今天是第一次寫,真心是有點小激動,正要下筆卻不知道應該從何說起,若是寫的不好,請各位見諒吧!關於網路請求,我自認為自己是一個菜鳥,沒有任何經驗,之前做的專案都是別人封裝好,告訴我怎麼呼叫就好了。至於怎麼封裝邏輯的,真是一竅不通,可近來