Flutter und JSON

Wer sich, und wenn es nur oberflächlich ist, mit programmieren befasst wird auf den Begriff JSON stoßen. Wenn man Großmama Google danach fragt, bekommt man von Großvater Wiki diese Definition angeboten:

Die JavaScript Object Notation, kurz JSON, ist ein kompaktes Datenformat in einer einfach lesbaren Textform zum Zweck des Datenaustauschs zwischen Anwendungen.

Ein Datenformat ist ein Standard, den sich jemand ausgedacht hat. Wieso und warum ist interessant, aber sekundär. JSON ist ein Datenaustausch Format und ist aktuell im Web weit verbreitet.
Viele Quellen mit denen man interagieren kann, bieten ihre Daten in diesen Format an.

In aller kürze (ohne ein Tutorial zu JSON ersetzen zu wollen) hier das wichtigste:


  • Der Inhalt eines JSON Files befindet sich entweder zwischen [..] oder {...} Klammern.
    [...] = Der Inhalt ist eine Liste. Diese Liste kann ein oder mehrere Objekte enthalten.
    {...} = Der Inhalt ist ein Objekt aus einem oder mehreren Schlüssel/Wert Paaren.
    Beispiel: { "Schlüssel" : "Ich bin der Wert zum Schlüssel" }
  • Zeichenketten müssen immer innerhalb doppelter Anführungszeichen stehen
  • mehrere Objekte werden durch Komma getrennt aneinandergereiht
Ein Objekt kann dabei, wiederum eine Liste mit Objekten enthalten, und diese Objekte wiederum Listen..die Struktur ist also beliebig verschachtelbar.

Wer noch nie mit JSON gearbeitet hat, kann auch diesen Artikel lesen oder besser gleich hier testen.
Wie immer bei meinen Artikeln ist der Code getestet und lauffähig (Visual Studio Code). 

Hier aber ein Beispiel: 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "name": "Frank Groller",
  "instrumente": [ "Harfe", "Violine", "Schlagzeug" ]
  "ort":  "Das zauberhafte Land von OZ",
  "sprachen": [
    { "sprache": "keltisch", "kenntnis": "gut" }
    { "sprache": "latein", "kenntnis": "gut" }
    { "sprache": "mandarin", "kenntnis": "schlecht" }
  ]
}

Notiz:Wenn wir den Code oben anschauen sehen wir "sprachen": [...] . sprachen fungiert hier natürlich als Schlüsse zu der Liste.

Im weiteren Verlauf sollten wir im Hinterkopf behalten, das in Dart [...] eine Liste meint, {...} jedoch eine Map. Das hat Auswirkungen darauf, was für Funktionen und Methoden uns zur Verfügung stehen.
Flutter / Dart ist natürlich auch darauf vorbereitet mit JSON umzugehen. Beginnen wir mit dem Beispiel:


Organisation und Import


Wir organisieren in diesem Beispiel den Code in drei Files: zwei Hauptfiles und einem Daten File. assets/data/message.json wird unsere JSON Daten enthalten. main.dart den Starter Code für das Beispiel. NachrichtListe.dart wird ein ListView Widget generieren, das unser JSON File auf den Bildschirm bringt.

Wieso importieren wir unsere JSON Daten nicht einfach als Dart File ?  Meine erste Antwort wäre: Ordnung ! Das mag in einem Beispiel nicht unbedingt notwendig sein. In grösseren Projekten durchaus :-)



In unserem pubspec.yaml File nehmen wir folgende Ergänzung vor:

1
2
  assets:
   - assets/data/message.json

Natürlich kann man das an eigene Bedürfnisse anpassen :-) Mit dieser Ergänzung binden wir das JSON File als Asset in unser Projekt ein. Hier liegt auch ein Unterschied zu dem einbinden der Daten als Dart File.

main.dart, message.json, NachrichtListe.dart


Nachfolgend das main.dart File:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import 'package:flutter/material.dart';

import 'NachrichtListe.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blueGrey,
        accentColor: Colors.red,
      ),
      home: MyHomePage(title: 'Flutter JSON Demo'),
    );
  }
}

Im Code oben importieren wir unser zweites File und haben als home: Eintrag unser Beispiel Widget.

Nun zu dem JSON File message.json:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
[ {
    "subject":"Meine erste Nachricht",
    "body": "Eu nulla pariatur labore consequat anim ullamco sint dolor officia."
  },
  {

    "subject":"Meine zweite Nachricht",
    "body": "Eu nulla pariatur labore consequat anim ullamco sint dolor officia."
  },
  {

    "subject":"Meine dritte Nachricht",
    "body": "Eu nulla pariatur labore consequat anim ullamco sint dolor officia."
  },
  {

    "subject":"Meine vierte Nachricht",
    "body": "Eu nulla pariatur labore consequat anim ullamco sint dolor officia."
  }
]

Es enthält vier Datensätze, die im "body": eine Lorem Ipsum Text enthalten. Für Visual Studio Code sind Erweiterungen verfügbar, die das einfügen solcher Texte vereinfachen. Sie dienen als Dummy Texte beziehungsweise als Platzhalter.

Wir haben den Einstieg in das Beispiel, das JSON File, nun zu dem Hauptteil des Codes, NachrichtListe.dart:


1
2
3
4
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

Wir importieren als erstes dart:convert. Diese Library gibt uns Zugriff auf die JSON Funktionalität von Dart. material.dart benötigen wir, wie fast immer und services.dart gibt uns Zugriff auf Services unserer Plattform (Android/iOS).
In diesem Beispiel benutzen wir ein StatefulWidget. Der Hauptgrund dafür wird ersichtlich wenn wir folgenden Code anschauen:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class _MyHomePageState extends State<MyHomePage> {

   List nachrichten = const [];

  Future loadNachrichtListe()async{

     var content = await rootBundle.loadString("assets/data/message.json");
     var collection = json.decode(content);
  
  setState(() {
   nachrichten = collection; 
  });
  }


  void initState(){
    loadNachrichtListe();
    super.initState();
  }

Im Code betrachten wir zuerst initState(...){...} :

Diese Funktion ist die erste die nach der Erzeugung unseres StatefulWidgets ausgeführt wird. Das heisst also, nach dem der Konstruktor des Stateful Widgets verarbeitet wurde

In der initState Funktion oben, rufen wir die Funktion loadNachrichtListe(...) auf. Diese asynchrone Funktion liest unser JSON File mittels rootBundle.loadString(...) als Zeichenkette ein und speichert sie in der Variable content.
Um diese Funktion nutzen zu können, haben wir ja weiter oben, services.dart importiert. Mit json.decode aus der dart:convert Library, wandeln wir das File um. Es liegt anschließend in collection vor.
Da wir mit await darauf warten das rootBundle.loadString unser File gelesen hat, wird json.decode und das anschließende setState( (...)..{...}); erst dann ausgeführt, wenn dies erfolgreich geschehen ist.

Wenn die Funktion loadNachrichtListe(...) ohne Fehler abgeschlossen wurde, kehrt der Code zu initState zurück und ruft super.initState(); auf. Diese Funktion ruft die initState Methode der Elternklasse auf. Da wir uns ja innerhalb einer initState(...) Funktion befinden, diese aber zu unserer MyHomePageState Klasse gehört, stellen wir so sicher, das die initState Funktion der Elternklasse auch ausgeführt wird. Das ist notwendig damit unser Widget ordnungsgemäss funktioniert.

Wir haben also unser JSON File geladen, es decodiert, in einer Variablen gespeichert und anschließend einer Dart List Variablen nachrichten übergeben. Die Daten liegen also vor und es geht nur noch darum sie darzustellen:



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView.separated(
        separatorBuilder: (BuildContext context, int index) => Divider(),
        itemCount: nachrichten.length,
        itemBuilder: (BuildContext context, int index) {
          var nachricht = nachrichten[index];
          return ListTile(
            isThreeLine: true,
            title: Text(nachricht['subject']),
            subtitle: Text(nachricht['body']),
            leading: CircleAvatar(
              child: Text("fb"),
            ),
          );
        },
      ),
      // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

Auf den Code oben werde ich in diesem Artikel nicht weiter eingehen. Wer sich noch über ListView.separated informieren möchte, schaut hier ! Bis bald !



Kommentare

Beliebte Posts aus diesem Blog

Dart Basic: abstract class Part 1

Flutter -- Tutorial Teil 6 Provider Part 1