smalljson
Transparently decode SmallJson-encoded API responses with a drop-in Dio interceptor.
Pairs with the nylo/smalljson Laravel package:
the server shrinks JSON responses with a compact structural encoding (plus optional
deflate), and SmallJsonInterceptor restores the original JSON before your app sees it.
Your models, decoders and error handling don't change at all.
- Zero app-code changes —
response.datais plain JSON data, exactly as if the server had never encoded it. Error responses (422 validation errors and friends) are decoded too. - Safe by negotiation — the interceptor advertises support with an
X-Small-Jsonrequest header; servers only encode for clients that ask. Responses are recognised by theirapplication/vnd.smalljson+jsoncontent type, so plain-JSON responses (and servers without the package) pass through untouched. - All platforms — pure Dart. Mode
z(deflate) usesdart:io, so web builds automatically advertise packed-only mode instead.
Getting started
dart pub add smalljson # or: flutter pub add smalljson
import 'package:dio/dio.dart';
import 'package:smalljson/smalljson.dart';
final dio = Dio(BaseOptions(baseUrl: 'https://api.example.com'))
..interceptors.add(SmallJsonInterceptor());
final response = await dio.get('/users');
print(response.data); // plain JSON — decoded transparently
That's it. The interceptor adds X-Small-Json: pz to every request, decodes any
SmallJson response body in place, and rewrites the response content type back to
application/json so downstream code (loggers, caches, model mappers) sees a completely
ordinary JSON response.
Using with Nylo
Register the interceptor on your API service:
class ApiService extends NyApiService {
ApiService({BuildContext? buildContext})
: super(buildContext, decoders: modelDecoders);
@override
String get baseUrl => getEnv('API_BASE_URL');
@override
Map<Type, Interceptor> get interceptors => {
...super.interceptors,
SmallJsonInterceptor: SmallJsonInterceptor(),
};
}
Everything else — network<User>(), decoders, caching — keeps working unchanged, just
with smaller payloads on the wire.
Options
SmallJsonInterceptor(
advertise: true, // add the request header (default true)
modes: 'pz', // advertised modes; defaults to the platform's best
rewriteContentType: true, // report application/json after decoding (default true)
requestHeader: 'X-Small-Json',// must match the server's smalljson.request_header
codec: SmallJsonCodec(), // swap in a configured codec if needed
)
Notes:
- Requests with
ResponseType.bytesorResponseType.streamare never touched — you asked for raw data, you get raw data. - A corrupt envelope surfaces as a
DioException(badResponse) whoseerroris aSmallJsonFormatException, rather than silently handing your app an undecoded envelope. - If you call the API from browsers as well, remember to whitelist
X-Small-Jsonin the server's CORSallowed_headers.
Manual use
The codec works without Dio — websockets, cached blobs, isolates:
const codec = SmallJsonCodec();
final data = codec.decode(envelope); // Map / String / UTF-8 bytes in
final envelope2 = codec.encode(data); // encode is symmetric (handy for tests)
One platform caveat inherited from JavaScript, not from SmallJson: on web builds, JSON
numbers like 1.0 decode as the integer 1 — identical to how plain JSON behaves there.
Testing
dart test # VM suite (100% line coverage of lib/)
dart test -p vm,chrome # additionally runs the web-platform tests in Chrome
License
MIT © Anthony Gordon
Libraries
- smalljson
- Transparently decode SmallJson-encoded API responses with Dio.