yet_another_json_isolate
JSON processing that never blocks the main isolate for long: small payloads are decoded inline, large payloads on short lived isolates that hand their result back without copying, and a large list is encoded on the main isolate in slices that yield to the event loop. On web, which has no isolates, every payload is decoded inline on the main thread.
Usage
import 'dart:typed_data';
import 'package:http/http.dart' as http;
import 'package:yet_another_json_isolate/yet_another_json_isolate.dart';
Future<void> main() async {
final isolate = YAJsonIsolate();
try {
// Serialize to a JSON string.
final String json = await isolate.encode({'title': 'Dune'});
// Serialize to UTF-8 encoded JSON bytes, such as an HTTP request body,
// without materializing the intermediate string.
final Uint8List requestBody = await isolate.encodeBytes([
{'title': 'Dune'},
{'title': 'Emma'},
]);
// Deserialize a JSON string.
final Object? book = await isolate.decode('{"title": "Dune"}');
// Deserialize UTF-8 encoded JSON bytes, such as an HTTP response body,
// without materializing the intermediate string on the calling isolate.
final response = await http.get(Uri.parse('https://example.com/books'));
final Object? data = await isolate.decodeBytes(response.bodyBytes);
} finally {
// Dispose when no longer needed, even when an operation throws.
await isolate.dispose();
}
}
AsyncJsonCodec
YAJsonIsolate implements AsyncJsonCodec, the interface the Supabase clients accept
through their jsonCodec parameter. Implement it to process their JSON some other way, for
example with a native parser, or to wrap the default implementation and measure it.
import 'dart:typed_data';
import 'package:yet_another_json_isolate/yet_another_json_isolate.dart';
class TimedJsonCodec implements AsyncJsonCodec {
TimedJsonCodec(this._inner);
final AsyncJsonCodec _inner;
@override
Future<dynamic> decode(String json) => _time(() => _inner.decode(json));
@override
Future<dynamic> decodeBytes(Uint8List encodedJson) =>
_time(() => _inner.decodeBytes(encodedJson));
@override
Future<String> encode(Object? json) => _time(() => _inner.encode(json));
@override
Future<Uint8List> encodeBytes(Object? json) =>
_time(() => _inner.encodeBytes(json));
@override
Future<void> dispose() => _inner.dispose();
Future<T> _time<T>(Future<T> Function() operation) async {
final stopwatch = Stopwatch()..start();
try {
return await operation();
} finally {
print('JSON took ${stopwatch.elapsedMicroseconds} µs');
}
}
}
License
This repo is licensed under MIT.
Libraries
- yet_another_json_isolate
- JSON encoding and decoding that never blocks the calling isolate for long: small payloads are decoded inline, large payloads on short lived isolates that hand their result back without copying, and a large list is encoded on the calling isolate in slices that yield to the event loop.