Skip to content

Instantly share code, notes, and snippets.

@matanlurey
Created January 22, 2019 00:27
Show Gist options
  • Save matanlurey/04ba622966fc301e9d3d44889f707ffa to your computer and use it in GitHub Desktop.
Save matanlurey/04ba622966fc301e9d3d44889f707ffa to your computer and use it in GitHub Desktop.
An extension of built_value's StandardJsonPlugin that supports custom enum types
import 'package:built_collection/built_collection.dart';
import 'package:built_value/standard_json_plugin.dart';
/// Extends [StandardJsonPlugin] but also understands custom/external enums.
///
/// See https://github.com/google/built_value.dart/issues/568.
///
/// Example use:
/// ```
/// import 'package:built_value/serializer.dart';
///
/// import 'custom_enum_json_plugin.dart';
///
/// void addJsonPlugin(SerializersBuilder builder) {
/// builder.addPlugin(CustomEnumJsonPlugin([
/// MyEnum1,
/// MyEnum2,
/// ]));
/// }
/// ```
class CustomEnumJsonPlugin extends StandardJsonPlugin {
final Set<Type> _customEnumTypes;
CustomEnumJsonPlugin(this._customEnumTypes);
@override
Object beforeDeserialize(object, type) {
if (type.root == BuiltMap && type.parameters.isNotEmpty) {
if (_customEnumTypes.contains(type.parameters.first.root)) {
object = _addEnumEncoding(object as Map<String, Object>);
}
}
return super.beforeDeserialize(object, type);
}
Map<String, Object> _addEnumEncoding(Map<String, Object> json) {
return json.map((key, value) {
return MapEntry('"$key"', {
valueKey: value,
discriminator: '${value.runtimeType}',
});
});
}
@override
Object afterSerialize(object, type) {
var json = super.afterSerialize(object, type);
if (type.root == BuiltMap && type.parameters.isNotEmpty) {
if (_customEnumTypes.contains(type.parameters.first.root)) {
json = _removeEnumEncoding(json as Map<String, Object>);
}
}
return json;
}
Map<String, Object> _removeEnumEncoding(Map<String, Object> json) {
return json.map((key, value) {
var valOut = value;
if (key is String && key.startsWith('"')) {
key = key.substring(1, key.length - 1);
}
if (value is Map && value.containsKey(discriminator)) {
valOut = value[valueKey];
}
return MapEntry(key, valOut);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment