What is the best way to serialize data from firebase to a Dart object for Flutter?

What is the best way to serialize a list of data from firebase? Firebase provides an object with a list of properties for the list, which makes it more difficult to come up with a good conversion technique.

How would you serialize this data from firebase ?:

  {
    "-KiRg_F-qC59xxlfZ6ej": {
    "first":"Brandon",
    "last":"Donnelson"
    },
    "-KiRgmsISBsJSWfXhrdD": {
    "first":"Danny",
    "last":"Kirk"
    }
  }

What I came up with: (See _loadData ())

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

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Text(
          'click',
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _test,
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ),);
  }

  void _test() {
    _loadData();
  }

  _loadData() async {
    String url = 'https://dev-xxxxxxx.firebaseio.com/names.json';
    var httpClient = createHttpClient();
    var response = await httpClient.read(url);

    print('response=' + response);
    // response={"-KiRg_F-qC59xxlfZ6ej":{"first":"Brandon","last":"Donnelson"},"-KiRgmsISBsJSWfXhrdD":{"first":"Danny","last":"Kirk"}}

    NamesData namesData = new NamesData(JSON.decode(response));

    print("names.len=" + namesData.names.length.toString());
  }
}

class NamesData {
  final List<NameData> names = new List();

  NamesData(Map data) {
    data.values.forEach((Map map) => names.add(new NameData.fromJson(map)));
  }
}

class NameData {
  String first;
  String last;

  NameData.fromJson(Map map) {
    first = map['first'];
    last = map['last'];
  }

}

I found that the json decoder has a better method for instantiating classes with the reviver function. It feels a lot better, but I think I can do better.

 _loadData() async {
      String url = 'https://dev-xxxxxxx.firebaseio.com/names.json';
      var httpClient = createHttpClient();
      var response = await httpClient.read(url);

      print('response=' + response);
      // response={"-KiRg_F-qC59xxlfZ6ej":{"first":"Brandon","last":"Donnelson"},"-KiRgmsISBsJSWfXhrdD":{"first":"Danny","last":"Kirk"}}

      var extendedJson =  new JsonCodec(reviver: _reviver);

      var o = extendedJson.decode(response);

      print('end');
    }

    // https://github.com/dart-lang/sdk/blob/master/tests/lib/convert/json_toEncodable_reviver_test.dart
    _reviver(key, value) {
      if (value != null && value is Map && key.toString().contains("-")) {
        return new NameData2(value);
      }
      return value;
    }

  }

  class NameData2 {
    String first;
    String last;

    NameData2(Map map) {
      first = map['first'];
      last = map['last'];
    }
  }
+7
source share
2 answers

I personally like to write tiny Codecsometimes:

DartPad Example

import 'dart:convert';

void main() {
  final decoder = const FirebaseNamesDecoder();
  print(decoder.convert(exampleFirebaseData));
}

class NamedData {
  final String id;
  final String firstName;
  final String lastName;

  const NamedData(this.id, this.firstName, this.lastName);

  @override
  String toString() => '$NamedData {$id: $firstName $lastName}';
}

class FirebaseNamesDecoder extends Converter<Map, Iterable<NamedData>> {
  const FirebaseNamesDecoder();

  @override
  Iterable<NamedData> convert(Map<String, Map> raw) {
    return raw.keys.map((id) => new NamedData(id, raw[id]['first'], raw[id]['last']));
  }
}

final exampleFirebaseData = {
  "-KiRg_F-qC59xxlfZ6ej": {
    "first":"Brandon",
    "last":"Donnelson"
  },
  "-KiRgmsISBsJSWfXhrdD": {
    "first":"Danny",
    "last":"Kirk"
  }
};

Results in:

(   NamedData {-KiRg_F-qC59xxlfZ6ej: },   NamedData {-KiRgmsISBsJSWfXhrdD: } )

+1

firebase?

.

import 'dart:convert';

import 'json_objects.dart';

void main(List<String> args) {
  var response =
      '{"-KiRg_F-qC59xxlfZ6ej":{"first":"Brandon","last":"Donnelson"},"-KiRgmsISBsJSWfXhrdD":{"first":"Danny","last":"Kirk"}}';

  var namesData =
      _deserialize(jsonDecode(response) as Map, (e) => NameData.fromJson(e));

  print("names.len=" + namesData.length.toString());
  for (var key in namesData.keys) {
    print(key);
    print('  ' + namesData[key].first + ' ' + namesData[key].last);
  }
}

Map<String, T> _deserialize<T>(Map map, T Function(Map) fromJson) {
  return map.map(
      (k, v) => MapEntry(k as String, v == null ? null : fromJson(v as Map)));
}

:

names.len=2
-KiRg_F-qC59xxlfZ6ej
  Brandon Donnelson
-KiRgmsISBsJSWfXhrdD
  Danny Kirk

:

// Generated by 'yaml2podo'
// Version: 0.1.15
// https://pub.dev/packages/yaml2podo

class NameData {
  final String first;
  final String last;

  NameData({this.first, this.last});

  factory NameData.fromJson(Map map) {
    return NameData(first: map['first'] as String, last: map['last'] as String);
  }

  Map<String, dynamic> toJson() {
    var result = <String, dynamic>{};
    result['first'] = first;
    result['last'] = last;
    return result;
  }
}

/*
NameData:
  first: String
  last: String
*/

0

Source: https://habr.com/ru/post/1675477/


All Articles