Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions packages/talker/lib/src/utils/json_formatter.dart
Original file line number Diff line number Diff line change
@@ -1,34 +1,44 @@
import 'dart:convert';

const _compactEncoder = JsonEncoder();
const _defaultEncoder = JsonEncoder.withIndent(' ');

/// Formatter for converting data to pretty JSON strings.
///
/// Use `const TalkerJsonFormatter()` for standard JSON formatting,
/// `TalkerJsonFormatter(prettyPrint: false)` for compact single-line JSON,
/// `TalkerJsonFormatter(stripQuotes: true)` to strip quotes,
/// or `TalkerJsonFormatter.custom(fn)` for custom formatting.
class TalkerJsonFormatter {
/// Creates a formatter with optional quote stripping.
/// Creates a formatter with optional quote stripping and pretty printing.
///
/// If [stripQuotes] is true, double quotes will be stripped from
/// the JSON output (except escaped quotes within values).
const TalkerJsonFormatter({this.stripQuotes = false})
: _customFormatter = null;
const TalkerJsonFormatter({
this.stripQuotes = false,
this.prettyPrint = true,
}) : _customFormatter = null;

/// Creates a formatter with a custom formatting function.
const TalkerJsonFormatter.custom(this._customFormatter) : stripQuotes = false;
const TalkerJsonFormatter.custom(this._customFormatter)
: stripQuotes = false,
prettyPrint = true;

/// Whether to strip double quotes from JSON output.
final bool stripQuotes;

/// Whether to format JSON with indentation.
final bool prettyPrint;

final String Function(dynamic data)? _customFormatter;

/// Formats the given data to a pretty JSON string.
String format(dynamic data) {
if (_customFormatter != null) {
return _customFormatter!(data);
}
final json = _defaultEncoder.convert(data);
final json =
(prettyPrint ? _defaultEncoder : _compactEncoder).convert(data);
if (stripQuotes) {
// Use \x00 (null byte) as a temporary placeholder for escaped quotes.
// This is safe because JsonEncoder escapes control characters (U+0000-U+001F)
Expand Down
9 changes: 9 additions & 0 deletions packages/talker/test/json_formatter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ void main() {
expect(result, contains('2'));
expect(result, contains('3'));
});

test('formats single-line JSON when prettyPrint is false', () {
const formatter = TalkerJsonFormatter(prettyPrint: false);
final result = formatter.format({'name': 'John', 'age': 30});

expect(result, equals('{"name":"John","age":30}'));
expect(result, isNot(contains('\n')));
});
});

group('stripQuotes', () {
Expand Down Expand Up @@ -96,6 +104,7 @@ void main() {
final formatter = TalkerJsonFormatter.custom((data) => 'CUSTOM: $data');

expect(formatter.stripQuotes, isFalse);
expect(formatter.prettyPrint, isTrue);
});
});

Expand Down
11 changes: 10 additions & 1 deletion packages/talker_dio_logger/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,16 @@ TalkerDioLoggerSettings(
)
```

### Log JSON in a single line

If you need copy-friendly JSON output, disable pretty printing in the formatter.

```dart
TalkerDioLoggerSettings(
jsonFormatter: const TalkerJsonFormatter(prettyPrint: false),
)
```

## Using with Talker
You can add your talker instance for TalkerDioLogger if your app already uses Talker.
In this case, all logs and errors will fall into your unified tracking system
Expand All @@ -118,4 +128,3 @@ dio.interceptors.add(TalkerDioLogger(talker: talker));
## Additional information
The project is under development and ready for your pull-requests and issues 👍<br>
Thank you for support ❤️

Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class TalkerDioLoggerSettings {

/// JSON formatter for converting data to pretty string.
/// Use [TalkerJsonFormatter] for default formatting,
/// [TalkerJsonFormatter(prettyPrint: false)] for single-line JSON,
/// [TalkerJsonFormatter(stripQuotes: true)] to strip quotes,
/// or [TalkerJsonFormatter.custom(fn)] for custom formatting.
final TalkerJsonFormatter jsonFormatter;
Expand Down
27 changes: 27 additions & 0 deletions packages/talker_dio_logger/test/logs_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,33 @@ void main() {
expect(result, contains('Data: CUSTOM:{key: value}'));
});

test('generateTextMessage should support single-line JSON formatting', () {
final response = Response(
requestOptions: RequestOptions(path: '/test', method: 'GET'),
statusCode: 200,
data: {
'key': 'value',
'nested': {'id': 1}
},
);
final settings = TalkerDioLoggerSettings(
jsonFormatter: TalkerJsonFormatter(prettyPrint: false),
);
final dioResponseLog = DioResponseLog(
'Test message',
response: response,
settings: settings,
);

final result = dioResponseLog.generateTextMessage();

expect(
result,
contains('Data: {"key":"value","nested":{"id":1}}'),
);
expect(result, isNot(contains('\n "key"')));
});

test('generateTextMessage should strip quotes in headers', () {
final response = Response(
requestOptions: RequestOptions(path: '/test', method: 'GET'),
Expand Down