Add JSON serialization (dart-lang/timing#6)

diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md
index 090fc36..7b73c71 100644
--- a/pkgs/timing/CHANGELOG.md
+++ b/pkgs/timing/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.1.1
+
+- Add JSON serialization
+
 ## 0.1.0
 
 - Initial release
diff --git a/pkgs/timing/README.md b/pkgs/timing/README.md
index a1518ea..400bc4b 100644
--- a/pkgs/timing/README.md
+++ b/pkgs/timing/README.md
@@ -10,4 +10,13 @@
 
 // Use results
 print('${tracker.duration} ${tracker.innerDuration} ${tracker.slices}');
+```
+
+
+## Building
+
+Use the following command to re-generate `lib/src/timing.g.dart` file:
+
+```bash
+pub run build_runner build
 ```
\ No newline at end of file
diff --git a/pkgs/timing/lib/src/timing.dart b/pkgs/timing/lib/src/timing.dart
index a1d5a85..15e8854 100644
--- a/pkgs/timing/lib/src/timing.dart
+++ b/pkgs/timing/lib/src/timing.dart
@@ -4,10 +4,15 @@
 
 import 'dart:async';
 
+import 'package:json_annotation/json_annotation.dart';
+
 import 'clock.dart';
 
+part 'timing.g.dart';
+
 /// The timings of an operation, including its [startTime], [stopTime], and
 /// [duration].
+@JsonSerializable(nullable: false)
 class TimeSlice {
   /// The total duration of this operation, equivalent to taking the difference
   /// between [stopTime] and [startTime].
@@ -19,12 +24,18 @@
 
   TimeSlice(this.startTime, this.stopTime);
 
+  factory TimeSlice.fromJson(Map<String, dynamic> json) =>
+      _$TimeSliceFromJson(json);
+
+  Map<String, dynamic> toJson() => _$TimeSliceToJson(this);
+
   @override
   String toString() => '($startTime + $duration)';
 }
 
 /// The timings of an async operation, consist of several sync [slices] and
 /// includes total [startTime], [stopTime], and [duration].
+@JsonSerializable(nullable: false)
 class TimeSliceGroup implements TimeSlice {
   final List<TimeSlice> slices;
 
@@ -51,6 +62,13 @@
 
   TimeSliceGroup(List<TimeSlice> this.slices);
 
+  /// Constructs TimeSliceGroup from JSON representation
+  factory TimeSliceGroup.fromJson(Map<String, dynamic> json) =>
+      _$TimeSliceGroupFromJson(json);
+
+  @override
+  Map<String, dynamic> toJson() => _$TimeSliceGroupToJson(this);
+
   @override
   String toString() => slices.toString();
 }
@@ -139,6 +157,12 @@
 
   @override
   Duration get duration => stopTime?.difference(startTime);
+
+  /// Converts to JSON representation
+  ///
+  /// Can't be used before [isFinished]
+  @override
+  Map<String, dynamic> toJson() => _$TimeSliceToJson(this);
 }
 
 /// Async actions returning [Future] will be tracked as single sync time span
@@ -196,6 +220,10 @@
 
   @override
   T track<T>(T Function() action) => action();
+
+  @override
+  Map<String, dynamic> toJson() =>
+      throw UnsupportedError('Unsupported in no-op implementation');
 }
 
 /// Track all async execution as disjoint time [slices] in ascending order.
diff --git a/pkgs/timing/lib/src/timing.g.dart b/pkgs/timing/lib/src/timing.g.dart
new file mode 100644
index 0000000..214dd82
--- /dev/null
+++ b/pkgs/timing/lib/src/timing.g.dart
@@ -0,0 +1,26 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'timing.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+TimeSlice _$TimeSliceFromJson(Map<String, dynamic> json) {
+  return TimeSlice(DateTime.parse(json['startTime'] as String),
+      DateTime.parse(json['stopTime'] as String));
+}
+
+Map<String, dynamic> _$TimeSliceToJson(TimeSlice instance) => <String, dynamic>{
+      'startTime': instance.startTime.toIso8601String(),
+      'stopTime': instance.stopTime.toIso8601String()
+    };
+
+TimeSliceGroup _$TimeSliceGroupFromJson(Map<String, dynamic> json) {
+  return TimeSliceGroup((json['slices'] as List)
+      .map((e) => TimeSlice.fromJson(e as Map<String, dynamic>))
+      .toList());
+}
+
+Map<String, dynamic> _$TimeSliceGroupToJson(TimeSliceGroup instance) =>
+    <String, dynamic>{'slices': instance.slices};
diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml
index 6b47c47..890555d 100644
--- a/pkgs/timing/pubspec.yaml
+++ b/pkgs/timing/pubspec.yaml
@@ -7,6 +7,11 @@
 environment:
   sdk: ">=2.0.0 <3.0.0"
 
+dependencies:
+  json_annotation: ^1.0.0
+
 dev_dependencies:
+  build_runner: ^0.10.0
+  json_serializable: ^1.0.0
   pedantic: 1.1.0
   test: ^1.0.0