用JSON序列化/反序列化Dart新枚举的最佳方法是什么?

mon*_*r75 5 enums json dart

我想利用Dart的新(实验性)enum功能,而不是使用静态const字符串堆栈,但是enum使用JSON 序列化/反序列化变量的最佳方法是什么?我已经通过这种方式使其工作,但是肯定有更好的解决方案:

enum Status {
  none,
  running,
  stopped,
  paused
}

Status status1 = Status.stopped;
Status status2 = Status.none;

String json = JSON.encode(status1.index);
print(json);   // prints 2

int index = JSON.decode(json);
status2 = Status.values[index];
print(status2);  // prints Status.stopped
Run Code Online (Sandbox Code Playgroud)

如果使用索引进行序列化,则可能会被锁定为永远使枚举始终保持相同的顺序,因此我更喜欢使用某种String形式。有人知道了吗?

Ano*_*P.A 13

使用枚举的name属性和 byName方法

这是一个示例代码来展示如何使用它:

import 'dart:convert';

void main() {
  Person raj = Person(name: 'Raj', favIcecream: Icecream.pista);
  print(raj.toJson());

  Person rajV2 = Person.fromJson(raj.toJson());
  print(rajV2.toJson());

  final isBothInstanceEqual = raj == rajV2;
  print('> Both instancecs are equal is $isBothInstanceEqual');
}

enum Icecream {
  vanilla,
  pista,
  strawberry,
}

class Person {
  String name;
  Icecream favIcecream;
  Person({
    required this.name,
    required this.favIcecream,
  });

  Map<String, dynamic> toMap() {
    return {
      'name': name,
      'favIcecream': favIcecream.name, // <- this is how you should save
    };
  }

  factory Person.fromMap(Map<String, dynamic> map) {
    return Person(
      name: map['name'] ?? '',
      favIcecream: Icecream.values.byName(map['favIcecream']), // <- back to enum
    );
  }

  String toJson() => json.encode(toMap());

  factory Person.fromJson(String source) => Person.fromMap(json.decode(source));

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is Person &&
        other.name == name &&
        other.favIcecream == favIcecream;
  }

  @override
  int get hashCode => name.hashCode ^ favIcecream.hashCode;
}
Run Code Online (Sandbox Code Playgroud)

  • 使用 .name 属性的当前最佳答案的最早发布版本。为什么后来再次重复这个相同的答案会得到赞成票......不知道。你应该在这里获得荣誉。谢谢你! (2认同)

Mic*_*tek 8

如果您使用的是 Dart 2.15.0+ (Flutter 2.8.0+)

您可以使用name添加到枚举的新属性。

要将其转换为 json 值,你可以这样做

Status status1 = Status.stopped;
String jsonValue = status1.name;
print(jsonValue); // prints "stopped"
Run Code Online (Sandbox Code Playgroud)

要将其转换回枚举,您可以这样做

String jsonValue = "stopped";
Status deserializedStatus = Status.values.byName(jsonValue);
print(deserializedStatus); // prints "Status.stopped"
Run Code Online (Sandbox Code Playgroud)


Pie*_*aut 5

正如先前提出的答案之一,如果您在客户端和服务器上共享相同的实现,那么序列化名称是我认为的最佳方法,并尊重SOLID设计中的开放/封闭原则,并指出:

“软件实体(类,模块,功能等)应打开以进行扩展,但应关闭以进行修改”

如果您需要将另一个成员添加到Enum中,则使用索引而不是名称将混乱代码的所有逻辑。但是,使用名称将允许扩展名。

最后,对枚举的名称进行序列化,然后对其进行正确的反序列化,编写一个小函数,将一个枚举以字符串形式给出,遍历枚举的所有成员并返回适当的枚举。如:

Status getStatusFromString(String statusAsString) {
  for (Status element in Status.values) {
     if (element.toString() == statusAsString) {
        return element;
     }
  }
  return null;
}
Run Code Online (Sandbox Code Playgroud)

因此,要序列化:

Status status1 = Status.stopped;
String json = JSON.encode(status1.toString());
print(json) // prints {"Status.stopped"}
Run Code Online (Sandbox Code Playgroud)

并反序列化:

String statusAsString = JSON.decode(json);
Status deserializedStatus = getStatusFromString(statusAsString);
print(deserializedStatus) // prints Status.stopped
Run Code Online (Sandbox Code Playgroud)

这是到目前为止我发现的最好方法。希望这可以帮助 !

  • 是的,很不幸,这也是我所知道的最好方式。到目前为止,它的轻率和可能的性能后果使我根本无法使用枚举,而且也从未使用过需要序列化的数据(对我而言,大多数数据对我来说就是这样)。枚举实现是我不喜欢Dart的极少数事情之一。 (2认同)