google / google/built_value.dart

Supporting Firestore GeoPoint data type

Open
#615 1 comment 1 reaction 1 assignee Claimed by @davidmorgan View on GitHub
question
Dominant language
Dart
Stars
886
Forks
195
Avg merge
1d 11h
Merged PRs (30d)
4

Description

Hey @davidmorgan, I'm trying to integrate with Firestore's GeoPoint data type. I'm having difficulty, could you point me in the right direction?

This is what is coming to and from Firestore:
```datt
{
'name': 'Jimmy',
'location': GeoPoint(55.424359, -5.605486)
}
```

I've created GeoPoint built_value class:
```dart
part 'geo_point.g.dart';

abstract class GeoPoint implements Built {
static Serializer get serializer => _$geoPointSerializer;

num get longitiude;

num get latitude;

factory GeoPoint([updates(GeoPointBuilder b)]) = _$GeoPoint;
GeoPoint._();

factory GeoPoint.fromJsonMap(Map data) {
print('GeoPoint: from JOSN map: $data');
return serializers.deserializeWith(GeoPoint.serializer, data);
}
factory GeoPoint.withCoordinates(num latitude, num longitiude) {
print('GeoPoint: from lat: $latitude long: $longitiude ');
return GeoPoint((b) => b
..latitude = latitude
..longitiude = longitiude);
}

Map toJsonMap() {
return new Map.of(serializers.serialize(this,
specifiedType: const FullType(GeoPoint)))
.cast();
}
}
```
I've created a serializer:
```dart

import '../geo_point.dart';

class GeoPointPlugin implements SerializerPlugin {
/// The field used to specify the value type if needed. Defaults to `$`.
final String discriminator;

// The key used when there is just a single value, for example if serializing
// an `int`.
final String valueKey;

GeoPointPlugin({this.discriminator = r'$', this.valueKey = ''});

@override
Object beforeSerialize(Object object, FullType specifiedType) => object;

@override
Object afterSerialize(Object object, FullType specifiedType) {
if (object is GeoPoint && specifiedType.root != JsonObject)
return _toGeoPointString(object);
else
return object;
}

@override
Object beforeDeserialize(Object object, FullType specifiedType) {
if (object is String && object.substring(0, 8) == 'GeoPoint')
return _toGeoPoint(object);
else
return object;
}

@override
Object afterDeserialize(Object object, FullType specifiedType) {
return object;
}

GeoPoint _toGeoPoint(String serializedString) {
Match match = new RegExp(r"\((.*),(.*)\)").firstMatch(serializedString);
return GeoPoint.withCoordinates(
num.parse(match.group(1)), num.parse(match.group(2)));
}

String _toGeoPointString(GeoPoint gp) {
return 'GeoPoint(${gp.latitude}, ${gp.longitiude})';
}
}

```
I've then created a test:
```dart
group('GeoPoint with known specifiedType', () {
final data = GeoPoint.withCoordinates(55.424359, -5.605486);
final serialized = 'GeoPoint(55.424359, -5.605486)';
final specifiedType = const FullType(GeoPoint);

test('can be serialized', () {
expect(serializers.serialize(data, specifiedType: specifiedType),
serialized);
});

test('can be deserialized', () {
expect(serializers.deserialize(serialized, specifiedType: specifiedType),
data);
});
});
```
The test is failing with the following output:
```
Expected: 'GeoPoint(55.424359, -5.605486)'
Actual: {'longitiude': -5.605486, 'latitude': 55.424359}
Which: not an
package:test_api expect
test/models/geo_point_serializer_test.dart 15:7 main..
✖ GeoPoint with known specifiedType can be serialized
Deserializing 'GeoPoint {
longitiude=-5.605486,
latitude=55.424359,
}' to 'GeoPoint' failed due to: type '_$GeoPoint' is not a subtype of type 'Iterable' in type cast
package:built_value/src/built_json_serializers.dart 154:11 BuiltJsonSerializers._deserialize
package:built_value/src/built_json_serializers.dart 105:18 BuiltJsonSerializers.deserialize
test/models/geo_point_serializer_test.dart 20:26 main..
✖ GeoPoint with known specifiedType can be deserialized
```

Any help would be great.
Thanks

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.