繁体   English   中英

将数据从 Firebase 序列化为 Flutter 的 Dart 对象的最佳方法是什么?

[英]What's the best way to serialize data from Firebase into Dart object for Flutter?

从 Firebase 序列化数据列表的最佳方法是什么? Firebase 为对象提供了列表的属性列表,这使得提出好的转换技术更具挑战性。

您将如何从 Firebase 序列化此数据:

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

我想出了什么——见_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'];
  }
}

我发现 JSON 解码器有一个更好的方法来使用 reviver 函数实例化类。 这感觉好多了,但我认为我可以做得更好。

_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'];
  }
}

我个人有时喜欢编写一个小小的Codec

DartPad 示例

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"
  }
};

结果是:

( NamedData {-KiRg_F-qC59xxlfZ6ej: Brandon Donnelson}, NamedData {-KiRgmsISBsJSWfXhrdD: Danny Kirk})

Dart 2 需要修改重写的方法:

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

使用 dart:convert 手动序列化 JSON

Flutter 中的基本 JSON 序列化非常简单。 Flutter 有一个内置的 dart:convert 库,其中包括一个简单的 JSON 编码器和解码器。

以下示例 JSON 实现了一个简单的用户模型。

{"name":"John Smith","email":"john@example.com"}

使用 dart:convert,您可以通过两种方式序列化这个 JSON 模型。

1) 内联序列化 JSON

Map<String, dynamic> user = jsonDecode(jsonString);

print('Howdy, ${user['name']}!');
print('We sent the verification link to ${user['email']}.');

2) 在模型类中序列化 JSON

class User
{
 final Stringname;
 final Stringemail;

 User(this.name,this.email);

 User.fromJson(Map<String,dynamic>json):name=json['name'],email=json['email'];

 Map<String,dynamic>toJson()=>
 {
  'name':name,
  'email':email,
 };
}

解码逻辑的职责现在移到模型本身内部。 使用这种新方法,您可以轻松解码用户。

Map userMap = jsonDecode(jsonString);
var user = User.fromJson(userMap);
print('Howdy, ${user.name}!');
print('We sent the verification link to ${user.email}.');

我建议使用json_serializable它是由谷歌开发人员开发的,它可以轻松处理样板代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM