betacode

Dart JSON với thư viện dart:convert

  1. dart:convert
  2. jsonDecode(..)
  3. jsonDecode(..). JSON --> Dart
  4. jsonEncode(..)
  5. Практическое упражнение

1. dart:convert

In many Dart/Flutter applications, you quite often have to work with JSON-formatted data. In this article we will learn how to use the dart:convert library to manually parse JSON data. This is a built-in library in Dart and is suitable for small projects.
For applications with more complex JSON models, using dart:convert can quickly become tedious, repetitive, and lead to many small errors. In that case, you should use dart_json_mapper or json_serializable library.
  • Dart json serializable
  • Dart dart json mapper
Although there are many Dart JSON libraries provided by the community now, it is not as diverse as Java. You can ask the question "Is there any library equivalent to Java's GSON/Jackson/Moshi?". The answer is yes, it's dart_json_mapper.
As a simple library, dart:convert doesn't need any additional configuration and is the first JSON processing library you need to think about, for small projects.
Some functions are provided by the dart:convert library:
// JSON ==> Dart Object.
dynamic jsonDecode(
  String source, {
  Object? reviver(Object? key, Object? value)?,
}) 

// Dart Object ==> JSON
String jsonEncode(
  Object? object, {
  Object? toEncodable(Object? nonEncodable)?,
}) 

2. jsonDecode(..)

dynamic jsonDecode(
  String source, {
  Object? reviver(Object? key, Object? value)?,
}) 
The jsonDecode() function is used to parse a JSON text and return a Dart object. This function returns dynamic type. This return type can be:
  • Map<String,dynamic>
  • List<dynamic>
  • A Dart object if the reviver parameter is not null (see an example below).
Parameters:
  • source: A text in JSON format.
  • reviver: An optional function called for each property found during parsing this JSON text. The [key=null] parameter corresponds to the global JSON object. Leaf-level properties will be executed first, root-level properties will be executed last.
Ситуация, когда функция jsonDecode(json) возвращает объект Map<String,dynamic>:
Ситуация, когда функция jsonDecode(json) возвращает объект List<dynamic>:
var json1 = '''{
      "name": "John Smith",
      "email": "john@example.com",
      "salary": 5000,
      "addresses": ["Address 1", "Address 2"]
    }''';

Map<String, dynamic> map = jsonDecode(json1);
var json2 = '''
  [
    {"name": "Tom", "country": "American"},
    {"name": "Jerry", "country": "American"} 
  ] 
''';

List<dynamic> list = jsonDecode(json2);
Example: The jsonDecode() function returns a Map<String,dynamic>:
json_jsonDecode_ex1.dart
import 'dart:convert';

void main() {
  var jsonString = '''{
        "name": "John Smith",
        "email": "john@example.com",
        "salary": 5000,
        "addresses": ["Address 1", "Address 2"]
      }''';  
  Map<String, dynamic> map = jsonDecode(jsonString);

  for (var key in map.keys) {
    print('$key --> ${map[key]}');
  }
  print(' --- ');
 
  List<dynamic> addresses =  map['addresses'];
  for(String address in addresses) {
     print('Address: $address');
  }
}
Output:
name --> John Smith
email --> john@example.com
salary --> 5000
addresses --> [Address 1, Address 2]
 ---
Address: Address 1
Address: Address 2
Next example with more complex JSON:
json_jsonDecode_ex2.dart
import 'dart:convert';

void main() {
  var jsonString = '''{
        "name": "John Smith",
        "email": "john@example.com",
        "children": [ 
           {
             "name": "Jack Smith",
             "email": "jack@example.com"
           }, 
           {
             "name": "Harry Smith",
             "email": "harry@example.com"
           }
         ]
      }''';
  Map<String, dynamic> map = jsonDecode(jsonString);

  for (var key in map.keys) {
    print('$key --> ${map[key]}');
  }
  print(' --- ');

  List<dynamic> children = map['children'];
  for (dynamic child in children) {
    var childMap = child as Map<String, dynamic>;
    for (var k in childMap.keys) {
      print('  $k --> ${childMap[k]}');
    }
  }
}
Output:
name --> John Smith
email --> john@example.com
children --> [{name: Jack Smith, email: jack@example.com}, {name: Harry Smith, email: harry@example.com}]
 ---
  name --> Jack Smith
  email --> jack@example.com
  name --> Harry Smith
  email --> harry@example.com
Example: The jsonDecode() function returns a List<dynamic>:
json_jsonDecode_ex3.dart
import 'dart:convert';

void main() {
  var jsonString = '''[ 
      {
        "name": "Jack Smith",
        "email": "jack@example.com"
      }, 
      {
        "name": "Harry Smith",
        "email": "harry@example.com"
      }
  ]''';
  List<dynamic> list = jsonDecode(jsonString);

  for (var element in list) {
    var map = element as Map<String, dynamic>;
    for (var k in map.keys) {
      print('$k --> ${map[k]}');
    }
  }
}
Output:
name --> Jack Smith
email --> jack@example.com
name --> Harry Smith
email --> harry@example.com

3. jsonDecode(..). JSON --> Dart

Например, преобразуйте JSON в объект Dart.
json_to_dart_ex1.dart
import 'dart:convert';

void main() {
  var jsonString = '''{
        "name": "John Smith",
        "email": "john@example.com",
        "contact": {
           "address": "Address 1",
           "phone": "12345"
        }  
      }''';

  Employee emp = Employee.fromJsonString(jsonString);

  print('Emp Name: ${emp.name}');
  print('Emp Email: ${emp.email}');
  print('Address: ${emp.contact.address}');
}

class Employee {
  String name;
  String email;
  Contact contact;

  // Constructor
  Employee(this.name, this.email, this.contact);

  static Employee fromMap(Map<String, dynamic> map) {
    String name = map['name'];
    String email = map['email'];
    Map<String, dynamic> contactMap = map['contact'];
    Contact contact = Contact.fromMap(contactMap);

    return Employee(name, email, contact);
  }

  static Employee fromJsonString(String jsonString) {
    Map<String, dynamic> map = jsonDecode(jsonString);
    return fromMap(map);
  }
}

class Contact {
  String address;
  String phone;

  // Constructor
  Contact(this.address, this.phone);

  static Contact fromMap(Map<String, dynamic> map) {
    String address = map['address'];
    String phone = map['phone'];
    return Contact(address, phone);
  }

  static Contact fromJsonString(String jsonString) {
    Map<String, dynamic> map = jsonDecode(jsonString);
    return fromMap(map);
  }
}
Output:
Emp Name: John Smith
Emp Email: john@example.com
Address: Address 1
Example 2: JSON --> Dart
json_to_dart_ex2.dart
import 'dart:convert';

void main() {
  // Department and Staffs
  var jsonString = '''{
        "deptNo" : "D001",
        "deptName": "Sales", 
        "staffs": [
           { "name": "Tom", "phone": "111222"}, 
           { "name": "Jerry", "phone": "222333"}, 
           { "name": "Donald", "phone": "333444"} 
        ]
      }''';

  Department dept = Department.fromJsonString(jsonString);

  print('Dept No: ${dept.deptNo}');
  print('Dept Name: ${dept.deptName}');
  print('Staff Count: ${dept.staffs.length}');

  Staff firstStaff = dept.staffs[0];
  print("First Staff Name: ${firstStaff.name}");
}

class Department {
  String deptNo;
  String deptName;
  List<Staff> staffs;

  Department(this.deptNo, this.deptName, this.staffs);

  static Department fromMap(Map<String, dynamic> map) {
    String deptNo = map['deptNo'];
    String deptName = map['deptName'];
    List<dynamic> list = map["staffs"];
    List<Staff> staffs = list.map((dynamic e) => Staff.fromMap(e)).toList();
    return Department(deptNo, deptName, staffs);
  }

  static Department fromJsonString(String jsonString) {
    Map<String, dynamic> map = jsonDecode(jsonString);
    return fromMap(map);
  }
}

class Staff {
  String name;
  String phone;
  Staff(this.name, this.phone);

  static Staff fromMap(Map<String, dynamic> map) {
    String name = map['name'];
    String phone = map['phone'];
    return Staff(name, phone);
  }
}
Output:
Dept No: D001
Dept Name: Sales
Staff Count: 3
First Staff Name: Tom

4. jsonEncode(..)

String jsonEncode(
  Object? object, {
  Object? toEncodable(Object? nonEncodable)?,
})
The jsonEncode() function is used to convert a Dart object into a JSON text.
Parameters:
  • object: A Dart object.
  • toEncodable: An optional function used to convert non-encodable Dart objects into encodable objects. If this parameter is not provided, the toJson() function will be used as an alternative.
Example: A Dart object with all encodable properties:
// An Encodable object:
var employee = {
  'name': 'John Smith',
  'email': 'john@example.com',
  'contact': {
    'address': 'Address 1',
    'phone': '12345'
   }
};
Example: A Dart object with several encodable properties, and one non-encodable property:
var employee = {
  'name': 'John Smith', // Encodable
  'email': 'john@example.com', // Encodable
  'contact': Contact('Address 1', '12345') // Unencodable!!!
};
Example: Using the jsonEncode() function to convert a Dart object to JSON text:
json_jsonEncode_ex1.dart
import 'dart:convert';

void main() {
  // An Object (Looks like a JSON):
  var employee = {
    'name': 'John Smith',
    'email': 'john@example.com',
    'contact': {
      'address': 'Address 1',
      'phone': '12345'
     }
  };
  var jsonString = jsonEncode(employee);
  print(jsonString);
}
Output:
{"name":"John Smith","email":"john@example.com","contact":{"address":"Address 1","phone":"12345"}}
Example: Converting a Map object to JSON text:
json_jsonEncode_ex2.dart
import 'dart:convert';

void main() {
  var map = Map<String,dynamic>();
    
  map['name'] = 'John Smith';
  map['email'] = 'john@example.com';

  var jsonString = jsonEncode(map);
  print(jsonString);
}
Output:
{"name":"John Smith","email":"john@example.com"}
Example: Using jsonEncode() function with toEncodable parameter:
json_jsonEncode_toEncodable_ex1.dart
import 'dart:convert';
void main() {
  var contact = Contact('Address 1', '12345');
  var employee = {
    'name': 'John Smith', // Encodable
    'email': 'john@example.com', // Encodable
    'contact': contact // Un-encodable!!!
  };
  var jsonString = jsonEncode(employee, toEncodable: (nonEncodable) {
    if (nonEncodable is Contact) {
      return {
        'address': nonEncodable.address,
        'phone': nonEncodable.phone
      };
    }
    return null;
  });
  print(jsonString);
}

class Contact {
  String address;
  String phone;
  Contact(this.address, this.phone); // Constructor
}
Output:
{"name":"John Smith","email":"john@example.com","contact":{"address":"Address 1","phone":"12345"}}
Example: Using jsonEncode() function with toEncodable parameter:
json_jsonEncode_toEncodable_ex2.dart
import 'dart:convert';

void main() {
  var contact = Contact('Address 1', '12345');
  var employee = Employee('John Smith', 'john@example.com', contact);

  var jsonString = jsonEncode(employee, toEncodable: (nonEncodable) {
    if (nonEncodable is Contact) {
      return {
        'address': nonEncodable.address,
        'phone': nonEncodable.phone
      };
    } else if(nonEncodable is Employee) {
       return {
           'name': nonEncodable.name,
           'email': nonEncodable.email,
           'contact': nonEncodable.contact
       };
    }
  });
  print(jsonString);
}

class Contact {
  String address;
  String phone;
  Contact(this.address, this.phone); // Constructor
}

class Employee {
  String name;
  String email;
  Contact contact;
  Employee(this.name, this.email, this.contact); // Constructor
}

5. Практическое упражнение

  • Bài thực hành Dart phân tích JSON với gói dart:convert