Flutter中的Json解析-原生方式

在Flutter中,沒有像Android原生中可以利用Gson等庫通過反射將服務端返回的Json字符串直接轉換爲對應的實體類,需要自己去解析Json,而在實際解析中也碰到一些問題,以此文記錄下來;

一、Flutter中Json串的結構

在Flutter中的Json串中,存在兩種結構Map以及List;

1、Map結構

最常見的最基礎的Json結構,以花括號“{ }”爲起始,此類結構稱爲Map結構;

eg:

{
    "id" : "10086",
    "name" : "Jack",
    "phone" : "13311112222"
}

2、List結構

以“[ ]”方括號爲起始,在Android原生中爲數組,此類結構稱爲List結構;

eg:

[
    "student1",
    "student2",
    "student3"
]

二、Json串當做參數的格式

針對於以上兩種結構,我們在解析Json串時,將Json串作爲參數傳入方法中去解析,那麼,兩種結構分佈對應怎樣的參數格式呢?

1、Map結構

在Flutter中,Map結構對應的參數格式爲“Map<String, dynamic> map”,通過Map結構,將String類型的key鍵映射爲dynamic類型的值,一般Json串的key值均爲String類型,所以在Map中將key值得格式定位String;但後面的Value值類型並不確定,可以是String類型,也可以是Int類型,也可以是自定義實體類型,所以用動態的dynamic;

2、List結構

在Flutter中沒有數組類型,但是有List,對應的參數格式爲“List<dynamic> list”,通過方括號引起來的結構爲一個List結構,裏面的對象類型也爲動態;

三、複雜Json的分類解析

1、純Map結構

{"id" : "10086", "name" : "Jack", "phone" : "13311112222" }

對於以上結構,我們構建其實體類,並創建其factory修飾的構造方法:

class Student {
    String stuId;
    String stuName;
    String stuTel;

    Student({this.stuId, this.stuName, this.stuTel});

    factory Student.fromJson(Map<String, dynamic> json) {
        return Student(
            stuId : json["id"],
            stuName : json["name"],
            stuTel : json["phone"]
        )
    };
}

2、Map中包含List結構

{
    "id" : "10086",
    "students" : [
        "student1", 
        "student2", 
        "student3"
    ]
}

實體類:

class A {
    String id;
    List<String> students;

    A({this.id, this.students});

    factory A.fromJson(Map<String, dynamic> json) {
        return A(
            id : json["id"],
            students : json["students"]
        )
    };
}

以上結構爲Map中含有一個List結構,根據上面的方法,在獲取"students"這個key鍵的值時,我們會發現出現報錯“type 'List<dynamic>' is not a subtype of type 'List<String>'”,意思是我們要請求的是一個List<String>類型,但是我們獲取到的是一個List<dynamic>類型,程序無法識別類型,所以我們需要將這個類型手動去轉換一下;

var str = json["students"];
List<String> strList = new List<String>.from(str);
students: strList;

這裏是先將Json中的數組通過key值取出,存入到一個List<dynamic>類型的對象中,在顯示的創建List<String>,其中包含了剛剛拿到的數據,這裏就將dynamic類型改變爲String類型了;

3、Map結構的嵌套

{
    "id" : "10086",
    "student" : {
        "name" : "Jack",
        "phone" : "111111"
    }
}

這裏Student的實體類同上,在對象A的實體類中,我們獲取Student對象時如果繼續使用 student : json["student"],則會出現報錯“type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Student'”,意思是無法直接將Map中的Map結構映射爲Student對象,所以這裏需要我們做一次轉換:

student : Student.fromJson(json["student"]);

先取出key鍵“student”對應的Map結構對象,此時可以將Map結構作爲參數傳入到Student類的fromJson方法中去解析轉爲Student對象;

4、Map中嵌套含有Map的List結構

{
    "id" : "10086",
    "student" : [
        {
            "name" : "Jack",
            "phone" : "111111"
        },
        {
            "name" : "Tom",
            "phone" : "222222"
        }
    ]
}

在這裏A對象中包含一個String的id,以及List<Student>類型的students,我們從上往下分析,直接在A類中獲取students時會取出是一個List<dynamic>類型,無法直接識別爲Student類型,所以還需要再次轉換:

var list = json["students"] as List;
List<Student> stus = list.map((i) => Student.fromJson(i)).toList;

這裏首先將key鍵“students”取出,通過打日誌“print(list.runtimeType)”會發現,這個list的類型爲List<dynamic>,與我們上面步驟分析的是一樣的,然後通過Student的fromJson方法,去遍歷整個list列表,把list中的每個對象都映射爲對應的Student對象;

對應的實體類:

class A {
    String id;
    List<Student> students;

    A({this.id, this.students});

    factory A.fromJson(Map<String, dynamic> json) {
        var list = json["students"] as List;
        List<Student> stus = list.map((i) => Student.fromJson(i)).toList();
        return A(
            id : json["id"],
            students : stus
        )
    };
}

5、List中嵌套Map

[
    {
        "name" : "Jack",
        "phone" : "111111"
    },
    {
        "name" : "Tom",
        "phone" : "222222"
    }
]

在這裏Student對象依舊不變,但是這個整體是一個List<Student>對象,所以創建一個StudentList類對象,包含成員變量List<Student> students;但是在StudentList的fromJson方法中,參數不在是一個Map結構,而是要換成List結構,從數組中取出解析與第5步中相同:

factory StudentList.fromJson(List<dynamic> json) {
    List<Student> stus = new List<Student>();
    stus = json.map((i) => Student.fromJson(i)).toList();
    return StudentList(
        students : stus
    );
}

更多的複雜結構參考官網或者根據上面的步驟推導;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章