Flutter json 和 对象之间的转换

这里写的是 Flutter 自带的 convertjson 转换。下面以 3 个实例来说明。

一、自定义对象中不再嵌套其他对象:

class Student {
  String name;
  int age;

  Student({
    required this.name,
    required this.age,
  });

  /// 因为调用 jsonDecode 把 json 串转对象时,jsonDecode 方法的返回值是 map 类型,无法直接转成 Student 对象
  factory Student.fromJson(Map<String, dynamic> parsedJson) {
    return Student(
      name: parsedJson['name'],
      age: parsedJson['age'],
    );
  }

  /// 这个方法在对象转json的时候自动被调用
  Map toJson() {
    Map map = Map();
    map["name"] = this.name;
    map["age"] = this.age;
    return map;
  }
}
对象转 json 抽成方法了:
String _getJsonStr() {
  Student student = Student(name: "pig", age: 33);
  String jsonStr = jsonEncode(student);
  return jsonStr;
}

调用如下:

 String data = _getJsonStr();
 print("data = $data");

输出如下:
在这里插入图片描述

json 串转对象
String jsonStr = _getJsonStr();
var data = jsonDecode(jsonStr);
print("data = $data, runtimeType = ${data.runtimeType}");

输出如下:
在这里插入图片描述
可以看出这个 data 类型是 map 类型,此时还没有转成 Student 对象。
要转成 Student 需要如下调用:

 Student st = Student.fromJson(data);
 print("st runtimeType = ${st.runtimeType}, st name = ${st.name}");

在这里插入图片描述
通过 Student.fromJson 的方法,把 map 转成 Student 对象,Student.fromJson 是定义在 Student 类中的,如下:

 /// 因为调用 jsonDecode 把 json 串转对象时,jsonDecode 方法的返回值是 map 类型,无法直接转成 Student 对象
 factory Student.fromJson(Map<String, dynamic> parsedJson) {
   return Student(
     name: parsedJson['name'],
     age: parsedJson['age'],
   );
 }

方法很简单,就是把 map 中的数据取出来,构造成 Student 对象。

对象中嵌套对象

Student 类中嵌套 Grade 对象:

class Student {
  String name;
  int age;
  Grade grade;

  Student({required this.name,
    required this.age,
    required this.grade,
  });

  factory Student.fromJson(Map<String, dynamic> parsedJson) {
    return Student(
      name: parsedJson['name'],
      age: parsedJson['age'],
      grade: Grade.fromJson(parsedJson['grade']),
    );
  }

  Map toJson() {
    Map map = Map();
    map["name"] = this.name;
    map["age"] = this.age;
    map["grade"] = this.grade;
    return map;
  }
}

class Grade {
  String className;
  String title;

  Grade({required this.className, required this.title});

  factory Grade.fromJson(Map<String, dynamic> parsedJson) {
    return Grade(
      className: parsedJson['className'],
      title: parsedJson['title'],
    );
  }

  Map toJson() {
    Map map = Map();
    map["className"] = this.className;
    map["title"] = this.title;
    return map;
  }
}

没什么大的改变,主要就是 Student.fromJson 中获取 grade 的方式和获取普通变量的方式不一样,如下:

  factory Student.fromJson(Map<String, dynamic> parsedJson) {
    return Student(
      name: parsedJson['name'],
      age: parsedJson['age'],
      grade: Grade.fromJson(parsedJson['grade']),
    );
  }

因为 parsedJson['grade'] 得到的仍然是 map 类型,所以需要通过 Grade.fromJson 方法转成 Gradle 对象。

除了嵌套对象外还嵌套对象集合

Student 中除了包含 Grade 对象外,还包含 Address 的列表。

各个类的定义如下:

class Student {
  String name;
  int age;
  Grade grade;
  List<Address> addressList;

  Student(
      {required this.name,
        required this.age,
        required this.grade,
        required this.addressList});

  factory Student.fromJson(Map<String, dynamic> parsedJson) {
    /// addressList 是列表 和 grade 的处理方式不一样
    /// 方式 1
    List<Address> addressL = [];
    var list = parsedJson['addressList'];
    for (var address in list) {
      addressL.add(Address.fromJson(address));
    }

    /// 方式 2,显然方式2的更加优雅
    List<Address> addressL2 = (parsedJson['addressList'] as List<dynamic>)
        .map((e) => Address.fromJson(e))
        .toList();

    return Student(
      name: parsedJson['name'],
      age: parsedJson['age'],
      grade: Grade.fromJson(parsedJson['grade']),
      addressList: addressL2,
    );
  }

  Map toJson() {
    Map map = Map();
    map["name"] = this.name;
    map["age"] = this.age;
    map["grade"] = this.grade;
    map['addressList'] = this.addressList;
    return map;
  }
}


class Grade {
  String className;
  String title;

  Grade({required this.className, required this.title});

  factory Grade.fromJson(Map<String, dynamic> parsedJson) {
    return Grade(
      className: parsedJson['className'],
      title: parsedJson['title'],
    );
  }

  Map toJson() {
    Map map = Map();
    map["className"] = this.className;
    map["title"] = this.title;
    return map;
  }
}

class Address {
  String street;
  String district;

  Address({required this.street, required this.district});

  factory Address.fromJson(Map<String, dynamic> parsedJson) {
    return Address(
      street: parsedJson['street'],
      district: parsedJson['district'],
    );
  }

  Map toJson() {
    Map map = Map();
    map["street"] = this.street;
    map["district"] = this.district;
    return map;
  }
}

主要的区别依然是 Student.fromJson

factory Student.fromJson(Map<String, dynamic> parsedJson) {
    /// addressList 是列表 和 grade 的处理方式不一样
    /// 方式 1
    List<Address> addressL = [];
    var list = parsedJson['addressList'];
    for (var address in list) {
      addressL.add(Address.fromJson(address));
    }

    /// 方式 2,显然方式2的更加优雅
    List<Address> addressL2 = (parsedJson['addressList'] as List<dynamic>)
        .map((e) => Address.fromJson(e))
        .toList();

    return Student(
      name: parsedJson['name'],
      age: parsedJson['age'],
      grade: Grade.fromJson(parsedJson['grade']),
      addressList: addressL2,
    );
  }

上面的 var list = parsedJson['addressList']; 获取的类型是 List<dynamic>,是无法直接转成 List< Address>,所以需要遍历 list ,然后通过 Address.fromJson(address)list 里面的对象转成 Address 类型。

上面基本就说完了,其实你可以看看 json_serializable 这个插件,其实也是通过注解来实现上面类似的代码。


版权声明:本文为zhujiangtaotaise原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。