Skip to content

Commit 39c39ae

Browse files
authored
platform: Correctly handle integer-like numbers from JSON (#1531)
In JSON, an allowed representation for doubles without a fractional part like `1.0` is actually `1`. This is, for example, the behavior of [JSONEncoder][1]. When using `jsonDecode`, a `0` or `1` is deserialized to an `int`, which would then cause `Position.fromMap` to crash. Instead, use `toDouble()` to ensure that the value is converted to a `double`. [1]: https://developer.apple.com/documentation/foundation/jsonencoder
1 parent 026534d commit 39c39ae

File tree

4 files changed

+38
-8
lines changed

4 files changed

+38
-8
lines changed

geolocator_platform_interface/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 4.2.4
2+
3+
- Correctly handle integer-like numbers when decoding `Position` from JSON.
4+
15
## 4.2.3
26

37
- Fixes several grammar mistakes in the API documentation.

geolocator_platform_interface/lib/src/models/position.dart

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,14 @@ class Position {
154154
latitude: positionMap['latitude'],
155155
longitude: positionMap['longitude'],
156156
timestamp: timestamp,
157-
altitude: positionMap['altitude'] ?? 0.0,
158-
altitudeAccuracy: positionMap['altitude_accuracy'] ?? 0.0,
159-
accuracy: positionMap['accuracy'] ?? 0.0,
160-
heading: positionMap['heading'] ?? 0.0,
161-
headingAccuracy: positionMap['heading_accuracy'] ?? 0.0,
157+
altitude: _toDouble(positionMap['altitude']),
158+
altitudeAccuracy: _toDouble(positionMap['altitude_accuracy']),
159+
accuracy: _toDouble(positionMap['accuracy']),
160+
heading: _toDouble(positionMap['heading']),
161+
headingAccuracy: _toDouble(positionMap['heading_accuracy']),
162162
floor: positionMap['floor'],
163-
speed: positionMap['speed'] ?? 0.0,
164-
speedAccuracy: positionMap['speed_accuracy'] ?? 0.0,
163+
speed: _toDouble(positionMap['speed']),
164+
speedAccuracy: _toDouble(positionMap['speed_accuracy']),
165165
isMocked: positionMap['is_mocked'] ?? false,
166166
);
167167
}
@@ -182,4 +182,12 @@ class Position {
182182
'speed_accuracy': speedAccuracy,
183183
'is_mocked': isMocked,
184184
};
185+
186+
static double _toDouble(dynamic value) {
187+
if (value == null) {
188+
return 0.0;
189+
}
190+
191+
return value.toDouble();
192+
}
185193
}

geolocator_platform_interface/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: A common platform interface for the geolocator plugin.
33
repository: https://github.com/baseflow/flutter-geolocator/tree/main/geolocator_platform_interface
44
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
55
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
6-
version: 4.2.3
6+
version: 4.2.4
77

88
dependencies:
99
flutter:

geolocator_platform_interface/test/src/models/position_test.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:convert';
2+
13
import 'package:flutter_test/flutter_test.dart';
24
import 'package:geolocator_platform_interface/geolocator_platform_interface.dart';
35

@@ -512,6 +514,22 @@ void main() {
512514
// Act & Assert
513515
expect(() => Position.fromMap(map), throwsArgumentError);
514516
});
517+
518+
test('fromMap should handle a map returned by jsonDecode', () {
519+
// Arrange
520+
const json = '''{
521+
"is_mocked": true,
522+
"longitude": -122.406417,
523+
"timestamp": 1718643179305.9131,
524+
"latitude": 37.785834000000001,
525+
"heading_accuracy": -1,
526+
"accuracy": 5,
527+
"heading": -1.5
528+
}''';
529+
530+
// Act & Assert
531+
expect(() => Position.fromMap(jsonDecode(json)), returnsNormally);
532+
});
515533
});
516534

517535
group('toString tests:', () {

0 commit comments

Comments
 (0)