codestory

Analysieren von JSON mit dart:convert

  1. dart:convert
  2. jsonDecode(..)
  3. jsonDecode(..). JSON --> Dart
  4. jsonEncode(..)
  5. Praktische Übung

1. dart:convert

In vielen Anwendungen Dart/Flutter müssen Sie häufig mit JSON-formatierten Daten arbeiten. In diesem Artikel erfahren Sie, wie Sie die dart:convert-Bibliothek verwenden, um JSON-Daten manuell zu parsen. Dies ist eine eingebaute Bibliothek in Dart und eignet sich für kleine Projekte.
Bei Anwendungen mit komplexeren JSON-Modellen kann die Verwendung von dart:convert schnell mühsam und repetitiv werden und zu vielen kleinen Fehlern führen. In diesem Fall sollten Sie die Bibliothek dart_json_mapper oder json_serializable verwenden.
  • Dart json serializable
Obwohl es mittlerweile viele Dart JSON-Bibliotheken gibt, die von der Community bereitgestellt werden, ist es nicht so vielfältig wie Java. Sie können die Frage stellen: „Gibt es eine Bibliothek, die GSON/Jackson/Moshi vom Java entspricht?“. Die Antwort ist ja, es ist dart_json_mapper.
Als einfache Bibliothek benötigt dart:convert keine zusätzliche Konfiguration und ist die erste JSON-Verarbeitungsbibliothek, an die Sie für kleine Projekte denken müssen.
Einige Funktionen werden von der Bibliothek dart:convert bereitgestellt:
// 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)?,
}) 
Die Funktion jsonDecode() wird verwendet, um einen JSON-Text zu parsen und ein Dart-Objekt zurückzugeben. Diese Funktion gibt den Typ dynamic zurück. Dieser Rückgabetyp kann sein:
  • Map<String,dynamic>
  • List<dynamic>
  • Ein Dart-Objekt, wenn der Parameter reviver nicht null ist (siehe Beispiel unten).
Parameter:
  • source: Ein Text im JSON-Format.
  • reviver: Eine optionale Funktion, die für jede Eigenschaft aufgerufen wird, die beim Analysieren dieses JSON-Texts gefunden wird. Der Parameter [key=null] entspricht dem globalen JSON-Objekt. Eigenschaften auf Blattebene werden zuerst ausgeführt, Eigenschaften auf Stammebene werden zuletzt ausgeführt.
Situation, in der die Funktion jsonDecode(json) ein Map<String,dynamic>-Objekt zurückgibt:
Situation, in der die Funktion jsonDecode(json) ein List<dynamic>-Objekt zurückgibt:
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);
Beispiel: Die Funktion jsonDecode() gibt eine Map<String,dynamic> zurück:
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
Nächstes Beispiel mit komplexerem 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
Beispiel: Die Funktion jsonDecode() gibt eine List<dynamic> zurück:
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

Konvertieren Sie beispielsweise ein JSON in ein Dart-Objekt.
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)?,
})
Die Funktion jsonEncode() wird verwendet, um ein Objekt Dart in einen JSON-Text umzuwandeln.
Die Parameters:
  • object: Ein Objekt Dart.
  • toEncodable: Eine optionale Funktion, die verwendet wird, um nicht kodierbare Dart-Objekte in kodierbare Objekte umzuwandeln. Wenn dieser Parameter nicht angegeben wird, wird alternativ die Funktion toJson() verwendet.
Beispiel: Ein Dart-Objekt mit allen codierbaren Eigenschaften:
// An Encodable object:
var employee = {
  'name': 'John Smith',
  'email': 'john@example.com',
  'contact': {
    'address': 'Address 1',
    'phone': '12345'
   }
};
Beispiel: Ein Dart-Objekt mit mehreren kodierbaren Eigenschaften und einer nicht kodierbaren Eigenschaft:
var employee = {
  'name': 'John Smith', // Encodable
  'email': 'john@example.com', // Encodable
  'contact': Contact('Address 1', '12345') // Unencodable!!!
};
Beispiel: Verwenden der Funktion jsonEncode() zum Konvertieren eines Dar-Objekts in 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"}}
Beispiel: Konvertieren eines Map-Objekts in 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"}
Beispiel: Verwendung der Funktion jsonEncode() mit dem Parameter toEncodable:
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"}}
Beispiel: Verwendund der Funktion jsonEncode() mit dem Parameter toEncodable:
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. Praktische Übung

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