From 72e34053f7b589cb760df731ffb5ac763ed543c6 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Wed, 21 Aug 2024 08:03:27 +0200 Subject: [PATCH 01/69] json Initial commit The code still needs a lot of work. It has no support yet for: - additional data - enums - collections - events It does run the first unit test however so the foundation seems to be good. --- .vscode/settings.json | 3 + packages/kiota_serialization_json/.gitignore | 7 + .../kiota_serialization_json/CHANGELOG.md | 4 + packages/kiota_serialization_json/README.md | 21 +++ .../analysis_options.yaml | 1 + .../lib/kiota_serialization_json.dart | 16 ++ .../lib/src/json_parse_node.dart | 120 +++++++++++++++ .../lib/src/json_parse_node_factory.dart | 17 +++ .../lib/src/json_serialization_writer.dart | 141 +++++++++++++++++ .../json_serialization_writer_factory.dart | 17 +++ .../kiota_serialization_json/pubspec.yaml | 22 +++ .../test/derived_microsoft_graph_user.dart | 20 +++ .../test/json_parse_node_test.dart | 142 ++++++++++++++++++ .../test/microsoft_graph_user.dart | 72 +++++++++ 14 files changed, 603 insertions(+) create mode 100644 .vscode/settings.json create mode 100644 packages/kiota_serialization_json/.gitignore create mode 100644 packages/kiota_serialization_json/CHANGELOG.md create mode 100644 packages/kiota_serialization_json/README.md create mode 100644 packages/kiota_serialization_json/analysis_options.yaml create mode 100644 packages/kiota_serialization_json/lib/kiota_serialization_json.dart create mode 100644 packages/kiota_serialization_json/lib/src/json_parse_node.dart create mode 100644 packages/kiota_serialization_json/lib/src/json_parse_node_factory.dart create mode 100644 packages/kiota_serialization_json/lib/src/json_serialization_writer.dart create mode 100644 packages/kiota_serialization_json/lib/src/json_serialization_writer_factory.dart create mode 100644 packages/kiota_serialization_json/pubspec.yaml create mode 100644 packages/kiota_serialization_json/test/derived_microsoft_graph_user.dart create mode 100644 packages/kiota_serialization_json/test/json_parse_node_test.dart create mode 100644 packages/kiota_serialization_json/test/microsoft_graph_user.dart diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..082b194 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "makefile.configureOnOpen": false +} \ No newline at end of file diff --git a/packages/kiota_serialization_json/.gitignore b/packages/kiota_serialization_json/.gitignore new file mode 100644 index 0000000..3cceda5 --- /dev/null +++ b/packages/kiota_serialization_json/.gitignore @@ -0,0 +1,7 @@ +# https://dart.dev/guides/libraries/private-files +# Created by `dart pub` +.dart_tool/ + +# Avoid committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock diff --git a/packages/kiota_serialization_json/CHANGELOG.md b/packages/kiota_serialization_json/CHANGELOG.md new file mode 100644 index 0000000..5f91eb2 --- /dev/null +++ b/packages/kiota_serialization_json/CHANGELOG.md @@ -0,0 +1,4 @@ +# Unreleased + +- Initial version. +- Provides parsing and serialization support for the `application/json` content type. diff --git a/packages/kiota_serialization_json/README.md b/packages/kiota_serialization_json/README.md new file mode 100644 index 0000000..a46affc --- /dev/null +++ b/packages/kiota_serialization_json/README.md @@ -0,0 +1,21 @@ +The `kiota_serialization_json` package is the Dart Text serialization library implementation to +handle `application/json` responses. + +## Usage + +Install the package in the generated project: + +> For now, you can add the git repository as a dependency in your `pubspec.yaml` file: +> +> ```yaml +> dependencies: +> kiota_serialization_text: +> git: +> url: https://github.com/ricardoboss/dart_kiota.git +> ref: main +> path: packages/kiota_serialization_json +> ``` + +```bash +dart pub add kiota_serialization_json +``` diff --git a/packages/kiota_serialization_json/analysis_options.yaml b/packages/kiota_serialization_json/analysis_options.yaml new file mode 100644 index 0000000..feb86ff --- /dev/null +++ b/packages/kiota_serialization_json/analysis_options.yaml @@ -0,0 +1 @@ +include: package:strict/analysis_options.yaml diff --git a/packages/kiota_serialization_json/lib/kiota_serialization_json.dart b/packages/kiota_serialization_json/lib/kiota_serialization_json.dart new file mode 100644 index 0000000..14e749f --- /dev/null +++ b/packages/kiota_serialization_json/lib/kiota_serialization_json.dart @@ -0,0 +1,16 @@ +/// This library implements deserialization for application/json responses. +/// +/// This library is not meant to be used directly, but rather to be used as a +/// dependency in the generated code. +library kiota_serialization_json; + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:kiota_abstractions/kiota_abstractions.dart'; +import 'package:uuid/uuid_value.dart'; + +part 'src/json_parse_node.dart'; +part 'src/json_parse_node_factory.dart'; +part 'src/json_serialization_writer.dart'; +part 'src/json_serialization_writer_factory.dart'; diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart new file mode 100644 index 0000000..03ca68b --- /dev/null +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -0,0 +1,120 @@ +part of '../kiota_serialization_json.dart'; + +class JsonParseNode implements ParseNode { + JsonParseNode(this._json); + + final dynamic _json; + + @override + ParsableHook? onAfterAssignFieldValues; + + @override + ParsableHook? onBeforeAssignFieldValues; + + @override + bool? getBoolValue() { + return _json == null ? null : bool.tryParse(_json.toString()); + } + + @override + Uint8List? getByteArrayValue() { + return _json == null ? null : base64Decode(_json.toString()); + } + + @override + ParseNode? getChildNode(String identifier) { + return null; + } + + @override + Iterable getCollectionOfEnumValues(EnumFactory parser) { + return []; + } + + @override + Iterable getCollectionOfObjectValues( + ParsableFactory factory, + ) { + return []; + } + + @override + Iterable getCollectionOfPrimitiveValues() { + return []; + } + + @override + DateOnly? getDateOnlyValue() { + return _json == null ? null : DateOnly.fromDateTimeString(_json.toString()); + } + + @override + DateTime? getDateTimeValue() { + return _json == null ? null : DateTime.tryParse(_json.toString()); + } + + @override + double? getDoubleValue() { + return _json == null ? null : double.tryParse(_json.toString()); + } + + @override + Duration? getDurationValue() { + return _json == null ? null : DurationExtensions.tryParse(_json.toString()); + } + + @override + T? getEnumValue(EnumFactory parser) { + // if (_json == null || _json.isEmpty) { + // return null; + // } + // TODO(kees): Restore original code above + return parser(_json.toString()); + } + + @override + UuidValue? getGuidValue() { + return _json == null ? null : UuidValue.withValidation(_json.toString()); + } + + @override + int? getIntValue() { + return _json == null ? null : int.tryParse(_json.toString()); + } + + @override + T? getObjectValue(ParsableFactory factory) { + // TODO(Kees): Needs a proper implementation + final item = factory(this); + // OnBeforeAssignFieldValues?.Invoke(item); + _assignFieldValues(item); + // OnAfterAssignFieldValues?.Invoke(item); + return item; + } + + void _assignFieldValues(T item) { + final fieldDeserializers = item.getFieldDeserializers(); + + if (_json is Map) { + for (final entry in _json.entries) { + if (fieldDeserializers.containsKey(entry.key)) { + print('Found property: ${entry.key} to deserialize'); + + final fieldDeserializer = fieldDeserializers[entry.key]; + fieldDeserializer!.call(JsonParseNode(entry.value)); + } + } + } + } + + @override + String? getStringValue() { + final result = _json.toString(); + return result == 'null' ? null : result; + } + + @override + TimeOnly? getTimeOnlyValue() { + return _json == null ? null : TimeOnly.fromDateTimeString(_json.toString()); + } +} diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node_factory.dart b/packages/kiota_serialization_json/lib/src/json_parse_node_factory.dart new file mode 100644 index 0000000..986fe35 --- /dev/null +++ b/packages/kiota_serialization_json/lib/src/json_parse_node_factory.dart @@ -0,0 +1,17 @@ +part of '../kiota_serialization_json.dart'; + + +class JsonParseNodeFactory implements ParseNodeFactory { + @override + ParseNode getRootParseNode(String contentType, Uint8List content) { + if (contentType.toLowerCase() != validContentType) { + throw ArgumentError('Invalid content type'); + } + + final json = utf8.decode(content); + return JsonParseNode(jsonDecode(json)); + } + + @override + String get validContentType => 'application/json'; +} diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart new file mode 100644 index 0000000..10ff52fb --- /dev/null +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -0,0 +1,141 @@ +part of '../kiota_serialization_json.dart'; + +class JsonSerializationWriter implements SerializationWriter { + final StringBuffer _buffer = StringBuffer(); + bool _isFirst = true; + + static UnsupportedError _noStructuredDataError() { + return UnsupportedError('Text does not support structured data'); + } + + @override + ParsableHook? onAfterObjectSerialization; + + @override + ParsableHook? onBeforeObjectSerialization; + + @override + void Function(Parsable p, SerializationWriter w)? onStartObjectSerialization; + + @override + Uint8List getSerializedContent() { + return utf8.encode(_buffer.toString()); + } + + @override + void writeAdditionalData(Map value) { + throw _noStructuredDataError(); + } + + @override + void writeBoolValue(String? key, {bool? value}) { + writeStringValue(key, value?.toString()); + } + + @override + void writeByteArrayValue(String? key, Uint8List? value) { + writeStringValue(key, value == null ? null : base64Encode(value)); + } + + @override + void writeCollectionOfEnumValues( + String? key, + Iterable? values, + EnumSerializer serializer, + ) { + throw _noStructuredDataError(); + } + + @override + void writeCollectionOfObjectValues( + String? key, + Iterable? values, + ) { + throw _noStructuredDataError(); + } + + @override + void writeCollectionOfPrimitiveValues(String? key, Iterable? values) { + throw _noStructuredDataError(); + } + + @override + void writeDateTimeValue(String? key, DateTime? value) { + writeStringValue(key, value?.toIso8601String()); + } + + @override + void writeDoubleValue(String? key, double? value) { + writeStringValue(key, value?.toString()); + } + + @override + void writeEnumValue( + String? key, + T? value, + EnumSerializer serializer, + ) { + writeStringValue(key, serializer(value)); + } + + @override + void writeIntValue(String? key, int? value) { + writeStringValue(key, value?.toString()); + } + + @override + void writeNullValue(String? key) { + writeStringValue(key, 'null'); + } + + @override + void writeObjectValue( + String? key, + T? value, [ + Iterable? additionalValuesToMerge, + ]) { + throw _noStructuredDataError(); + } + + @override + void writeStringValue(String? key, String? value) { + // text cannot have keys, so we throw if one is provided + if (key?.isNotEmpty ?? false) { + throw _noStructuredDataError(); + } + + // if the value is null or empty, we don't write anything + if (value?.isEmpty ?? true) { + return; + } + + if (!_isFirst) { + throw UnsupportedError( + 'A value was already written for this serialization writer, text content only supports a single value', + ); + } + + _isFirst = false; + _buffer.write(value); + } + + @override + void writeDateOnlyValue(String? key, DateOnly? value) { + writeStringValue(key, value?.toRfc3339String()); + } + + @override + void writeDurationValue(String? key, Duration? value) { + writeStringValue(key, value?.toString()); + } + + @override + void writeTimeOnlyValue(String? key, TimeOnly? value) { + writeStringValue(key, value?.toRfc3339String()); + } + + @override + void writeUuidValue(String? key, UuidValue? value) { + writeStringValue(key, value?.uuid); + } +} diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer_factory.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer_factory.dart new file mode 100644 index 0000000..e2fce7e --- /dev/null +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer_factory.dart @@ -0,0 +1,17 @@ +part of '../kiota_serialization_json.dart'; + +class JsonSerializationWriterFactory implements SerializationWriterFactory { + @override + SerializationWriter getSerializationWriter(String contentType) { + if (contentType.toLowerCase() != validContentType) { + throw ArgumentError( + 'The provided content type is not supported by the JsonSerializationWriterFactory', + ); + } + + return JsonSerializationWriter(); + } + + @override + String get validContentType => 'application/json'; +} diff --git a/packages/kiota_serialization_json/pubspec.yaml b/packages/kiota_serialization_json/pubspec.yaml new file mode 100644 index 0000000..beba452 --- /dev/null +++ b/packages/kiota_serialization_json/pubspec.yaml @@ -0,0 +1,22 @@ +name: kiota_serialization_json +description: Provides parsing and serialization support for the `application/json` content type. +version: 0.0.1-pre.1 +repository: https://github.com/ricardoboss/dart_kiota +homepage: https://github.com/ricardoboss/dart_kiota/tree/main/packages/kiota_serialization_json +publish_to: 'none' + +environment: + sdk: '>=3.2.6 <4.0.0' + +# Add regular dependencies here. +dependencies: + kiota_abstractions: + path: ../kiota_abstractions + uuid: ^4.4.2 + +dev_dependencies: + strict: ^2.0.0 + test: ^1.25.2 + + + diff --git a/packages/kiota_serialization_json/test/derived_microsoft_graph_user.dart b/packages/kiota_serialization_json/test/derived_microsoft_graph_user.dart new file mode 100644 index 0000000..423263c --- /dev/null +++ b/packages/kiota_serialization_json/test/derived_microsoft_graph_user.dart @@ -0,0 +1,20 @@ +import 'package:kiota_abstractions/kiota_abstractions.dart'; + +import 'microsoft_graph_user.dart'; + +class DerivedMicrosoftGraphUser extends MicrosoftGraphUser { + DateOnly? enrolmentDate; + + @override + void serialize(SerializationWriter writer) { + super.serialize(writer); + writer.writeDateOnlyValue('enrolmentDate', enrolmentDate); + } + + @override + Map getFieldDeserializers() { + final parentDeserializers = super.getFieldDeserializers(); + parentDeserializers['enrolmentDate'] = (node) => enrolmentDate = node.getDateOnlyValue(); + return parentDeserializers; + } +} diff --git a/packages/kiota_serialization_json/test/json_parse_node_test.dart b/packages/kiota_serialization_json/test/json_parse_node_test.dart new file mode 100644 index 0000000..9398c56 --- /dev/null +++ b/packages/kiota_serialization_json/test/json_parse_node_test.dart @@ -0,0 +1,142 @@ +import 'dart:convert'; + +import 'package:kiota_abstractions/kiota_abstractions.dart'; +import 'package:kiota_serialization_json/kiota_serialization_json.dart'; +import 'package:test/test.dart'; + +import 'microsoft_graph_user.dart'; + +const _testUserJson = r''' +{ + "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity", + "@odata.id": "https://graph.microsoft.com/v2/dcd219dd-bc68-4b9b-bf0b-4a33a796be35/directoryObjects/48d31887-5fad-4d73-a9f5-3c356e68a038/Microsoft.DirectoryServices.User", + "businessPhones": [ + "+1 412 555 0109" + ], + "displayName": "Megan Bowen", + "numbers": "one,two,thirtytwo", + "testNamingEnum": "Item2:SubItem1", + "givenName": "Megan", + "accountEnabled": true, + "createdDateTime": "2017-07-29T03:07:25Z", + "jobTitle": "Auditor", + "mail": "MeganB@M365x214355.onmicrosoft.com", + "mobilePhone": null, + "officeLocation": null, + "preferredLanguage": "en-US", + "surname": "Bowen", + "workDuration": "PT1H", + "startWorkTime": "08:00:00.0000000", + "endWorkTime": "17:00:00.0000000", + "userPrincipalName": "MeganB@M365x214355.onmicrosoft.com", + "birthDay": "2017-09-04", + "id": "48d31887-5fad-4d73-a9f5-3c356e68a038" +}'''; + +const _testStudentJson = r''' +{ + "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity", + "@odata.type": "microsoft.graph.student", + "@odata.id": "https://graph.microsoft.com/v2/dcd219dd-bc68-4b9b-bf0b-4a33a796be35/directoryObjects/48d31887-5fad-4d73-a9f5-3c356e68a038/Microsoft.DirectoryServices.User", + "businessPhones": [ + "+1 412 555 0109" + ], + "displayName": "Megan Bowen", + "numbers": "one,two,thirtytwo", + "testNamingEnum": "Item2:SubItem1", + "givenName": "Megan", + "accountEnabled": true, + "createdDateTime": "2017-07-29T03:07:25Z", + "jobTitle": "Auditor", + "mail": "MeganB@M365x214355.onmicrosoft.com", + "mobilePhone": null, + "officeLocation": null, + "preferredLanguage": "en-US", + "surname": "Bowen", + "workDuration": "PT1H", + "startWorkTime": "08:00:00.0000000", + "endWorkTime": "17:00:00.0000000", + "userPrincipalName": "MeganB@M365x214355.onmicrosoft.com", + "birthDay": "2017-09-04", + "enrolmentDate": "2017-09-04, + "id": "48d31887-5fad-4d73-a9f5-3c356e68a038" +}'''; + +const _testUntypedJson = r''' +{ + "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('contoso.sharepoint.com')/lists('fa631c4d-ac9f-4884-a7f5-13c659d177e3')/items('1')/fields/$entity", + "id": "5", + "title": "Project 101", + "location": { + "address": { + "city": "Redmond", + "postalCode": "98052", + "state": "Washington", + "street": "NE 36th St" + }, + "coordinates": { + "latitude": 47.641942, + "longitude": -122.127222 + }, + "displayName": "Microsoft Building 92", + "floorCount": 50, + "hasReception": true, + "contact": null + }, + "keywords": [ + { + "created": "2023-07-26T10:41:26Z", + "label": "Keyword1", + "termGuid": "10e9cc83-b5a4-4c8d-8dab-4ada1252dd70", + "wssId": 6442450942 + }, + { + "created": "2023-07-26T10:51:26Z", + "label": "Keyword2", + "termGuid": "2cae6c6a-9bb8-4a78-afff-81b88e735fef", + "wssId": 6442450943 + } + ], + "detail": null, + "table": [[1,2,3],[4,5,6],[7,8,9]], + "extra": { + "createdDateTime": "2024-01-15T00:00:00\\u002B00:00" + } +}'''; + +const _testCollectionOfEnumsJson = ''' +[ + "Item2:SubItem1", + "Item3:SubItem1" +]'''; + +void main() { + group('JsonParseNode', () { + test('Get user object from Json', () { + final jsonParseNode = JsonParseNode(jsonDecode(_testUserJson)); + final testEntity = jsonParseNode + .getObjectValue(MicrosoftGraphUser.createFromDiscriminator); + + expect(testEntity, isNotNull); + if (testEntity != null) { + expect(testEntity.officeLocation, null); + // expect(testEntity.additionalData, isNotEmpty); + // expect(testEntity.additionalData.containsKey('jobTitle'), isTrue); + // expect(testEntity.AdditionalData.ContainsKey('mobilePhone'), isTrue); + // expect('Auditor', testEntity.additionalData['jobTitle']); + expect(testEntity.id, '48d31887-5fad-4d73-a9f5-3c356e68a038'); + // expect.Equal(TestEnum.One | TestEnum.Two, + // expect.teststEntity.Numbers); // Unknown enum value is not included + // expect.Equal(TestNamingEnum.Item2SubItem1, + // testEntity.TestNamingEnum); // correct value is chosen + // expect.Equal(TimeSpan.FromHours(1), + // testEntity.WorkDuration); // Parses timespan values + // expect.Equal(new Time(8, 0, 0).ToString(), + // testEntity.StartWorkTime.ToString()); // Parses time values + // expect.Equal(new Time(17, 0, 0).ToString(), + // testEntity.EndWorkTime.ToString()); // Parses time values + expect(testEntity.birthDay, DateOnly.fromComponents(2017, 9, 4)); + } + }); + }); +} diff --git a/packages/kiota_serialization_json/test/microsoft_graph_user.dart b/packages/kiota_serialization_json/test/microsoft_graph_user.dart new file mode 100644 index 0000000..6e1ee87 --- /dev/null +++ b/packages/kiota_serialization_json/test/microsoft_graph_user.dart @@ -0,0 +1,72 @@ +import 'package:kiota_abstractions/kiota_abstractions.dart'; + +import 'derived_microsoft_graph_user.dart'; + +class MicrosoftGraphUser + extends Parsable /* implements AdditionDataHolder */ { + MicrosoftGraphUser(); + + factory MicrosoftGraphUser.createFromDiscriminator(ParseNode parseNode) { + final discriminatorValue = + parseNode.getChildNode('@odata.type')?.getStringValue(); + return switch (discriminatorValue) { + 'microsoft.graph.user' => MicrosoftGraphUser(), + 'microsoft.graph.group' => MicrosoftGraphUser(), + 'microsoft.graph.student' => DerivedMicrosoftGraphUser(), + _ => MicrosoftGraphUser(), + }; + } + + // IDictionary AdditionalData { get; set; } + String? id; + // TestEnum? Numbers { get; set; } + // TestNamingEnum? TestNamingEnum { get; set; } + // TimeSpan? WorkDuration { get; set; } + DateOnly? birthDay; + TimeOnly? startWorkTime; + TimeOnly? endWorkTime; + // DateTimeOffset? CreatedDateTime { get; set; } + double? heightInMetres; + String? officeLocation; + + @override + void serialize(SerializationWriter writer) { + writer + ..writeStringValue('id', id) + // writer.writeEnumValue("numbers", Numbers); + // writer.writeEnumValue("testNamingEnum", TestNamingEnum); + // writer.writeDateTimeOffsetValue("createdDateTime", CreatedDateTime); + ..writeStringValue('officeLocation', officeLocation) + // writer.writeTimeSpanValue("workDuration", WorkDuration); + ..writeDateOnlyValue('birthDay', birthDay) + ..writeDoubleValue('heightInMetres', heightInMetres) + ..writeTimeOnlyValue('startWorkTime', startWorkTime) + ..writeTimeOnlyValue('endWorkTime', endWorkTime); + // writer.writeAdditionalData(AdditionalData); + } + + @override + Map getFieldDeserializers() { + return { + 'id': (node) => id = node.getStringValue(), + // 'numbers': (node) => numbers = node.getEnumValue(), + // 'testNamingEnum': (node) => testNamingEnum = node.getEnumValue(), + // 'createdDateTime': (node) => createdDateTime = node.getDateTimeOffsetValue(); + 'officeLocation': (node) => officeLocation = node.getStringValue(), + // 'workDuration': (node) => workDuration = node.getTimeSpanValue(), + 'heightInMetres': (node) => heightInMetres = node.getDoubleValue(), + 'birthDay': (node) => birthDay = node.getDateOnlyValue(), + 'startWorkTime': (node) => startWorkTime = node.getTimeOnlyValue(), + 'endWorkTime': (node) => endWorkTime = node.getTimeOnlyValue(), + }; + } + + @override + String toString() { + return ''' + id: $id + birthDay: $birthDay + officeLocation: $officeLocation + '''; + } +} From e936df47fac6af7f88135741824ae12e6ab58f2a Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Thu, 22 Aug 2024 07:40:00 +0200 Subject: [PATCH 02/69] json childNode enum duration support Due to implemnation of getChildNode, getting an object based on a discriminator works. Enums with a text value are supported (but not generically) Durations are supported. --- .../lib/src/json_parse_node.dart | 55 +++++++++++-------- .../test/derived_microsoft_graph_user.dart | 3 + .../test/json_parse_node_test.dart | 30 +++++++--- .../test/microsoft_graph_user.dart | 18 ++++-- .../test/test_enums.dart | 26 +++++++++ 5 files changed, 94 insertions(+), 38 deletions(-) create mode 100644 packages/kiota_serialization_json/test/test_enums.dart diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index 03ca68b..63edd3e 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -1,9 +1,9 @@ part of '../kiota_serialization_json.dart'; class JsonParseNode implements ParseNode { - JsonParseNode(this._json); + JsonParseNode(this._node); - final dynamic _json; + final dynamic _node; @override ParsableHook? onAfterAssignFieldValues; @@ -13,17 +13,28 @@ class JsonParseNode implements ParseNode { @override bool? getBoolValue() { - return _json == null ? null : bool.tryParse(_json.toString()); + return _node == null ? null : bool.tryParse(_node.toString()); } @override Uint8List? getByteArrayValue() { - return _json == null ? null : base64Decode(_json.toString()); + return _node == null ? null : base64Decode(_node.toString()); } @override ParseNode? getChildNode(String identifier) { - return null; + if (_node is Map) { + final childNode = _node[identifier]; + if (childNode != null) { + final result = JsonParseNode(childNode); + // TODO(Kees): Call on... events + // result.onBeforeAssignFieldValues((f) => onBeforeAssignFieldValues); + // result.onAfterAssignFieldValues(onAfterAssignFieldValues); + return result; + } + + return null; + } } @override @@ -45,61 +56,57 @@ class JsonParseNode implements ParseNode { @override DateOnly? getDateOnlyValue() { - return _json == null ? null : DateOnly.fromDateTimeString(_json.toString()); + return _node == null ? null : DateOnly.fromDateTimeString(_node.toString()); } @override DateTime? getDateTimeValue() { - return _json == null ? null : DateTime.tryParse(_json.toString()); + return _node == null ? null : DateTime.tryParse(_node.toString()); } @override double? getDoubleValue() { - return _json == null ? null : double.tryParse(_json.toString()); + return _node == null ? null : double.tryParse(_node.toString()); } @override Duration? getDurationValue() { - return _json == null ? null : DurationExtensions.tryParse(_json.toString()); + return _node == null ? null : DurationExtensions.tryParse(_node.toString()); } @override T? getEnumValue(EnumFactory parser) { - // if (_json == null || _json.isEmpty) { - // return null; - // } - // TODO(kees): Restore original code above - return parser(_json.toString()); + return _node == null ? null : parser(_node.toString()); } @override UuidValue? getGuidValue() { - return _json == null ? null : UuidValue.withValidation(_json.toString()); + return _node == null ? null : UuidValue.withValidation(_node.toString()); } @override int? getIntValue() { - return _json == null ? null : int.tryParse(_json.toString()); + return _node == null ? null : int.tryParse(_node.toString()); } @override T? getObjectValue(ParsableFactory factory) { - // TODO(Kees): Needs a proper implementation + // TODO(Kees): Handle getting untyped value final item = factory(this); - // OnBeforeAssignFieldValues?.Invoke(item); + onBeforeAssignFieldValues?.call(item); _assignFieldValues(item); - // OnAfterAssignFieldValues?.Invoke(item); + onAfterAssignFieldValues?.call(item); + return item; } void _assignFieldValues(T item) { final fieldDeserializers = item.getFieldDeserializers(); - if (_json is Map) { - for (final entry in _json.entries) { + if (_node is Map) { + for (final entry in _node.entries) { if (fieldDeserializers.containsKey(entry.key)) { print('Found property: ${entry.key} to deserialize'); - final fieldDeserializer = fieldDeserializers[entry.key]; fieldDeserializer!.call(JsonParseNode(entry.value)); } @@ -109,12 +116,12 @@ class JsonParseNode implements ParseNode { @override String? getStringValue() { - final result = _json.toString(); + final result = _node.toString(); return result == 'null' ? null : result; } @override TimeOnly? getTimeOnlyValue() { - return _json == null ? null : TimeOnly.fromDateTimeString(_json.toString()); + return _node == null ? null : TimeOnly.fromDateTimeString(_node.toString()); } } diff --git a/packages/kiota_serialization_json/test/derived_microsoft_graph_user.dart b/packages/kiota_serialization_json/test/derived_microsoft_graph_user.dart index 423263c..03d712d 100644 --- a/packages/kiota_serialization_json/test/derived_microsoft_graph_user.dart +++ b/packages/kiota_serialization_json/test/derived_microsoft_graph_user.dart @@ -3,6 +3,8 @@ import 'package:kiota_abstractions/kiota_abstractions.dart'; import 'microsoft_graph_user.dart'; class DerivedMicrosoftGraphUser extends MicrosoftGraphUser { + DerivedMicrosoftGraphUser(); + DateOnly? enrolmentDate; @override @@ -17,4 +19,5 @@ class DerivedMicrosoftGraphUser extends MicrosoftGraphUser { parentDeserializers['enrolmentDate'] = (node) => enrolmentDate = node.getDateOnlyValue(); return parentDeserializers; } + } diff --git a/packages/kiota_serialization_json/test/json_parse_node_test.dart b/packages/kiota_serialization_json/test/json_parse_node_test.dart index 9398c56..93b79e2 100644 --- a/packages/kiota_serialization_json/test/json_parse_node_test.dart +++ b/packages/kiota_serialization_json/test/json_parse_node_test.dart @@ -4,7 +4,9 @@ import 'package:kiota_abstractions/kiota_abstractions.dart'; import 'package:kiota_serialization_json/kiota_serialization_json.dart'; import 'package:test/test.dart'; +import 'derived_microsoft_graph_user.dart'; import 'microsoft_graph_user.dart'; +import 'test_enums.dart'; const _testUserJson = r''' { @@ -29,7 +31,7 @@ const _testUserJson = r''' "startWorkTime": "08:00:00.0000000", "endWorkTime": "17:00:00.0000000", "userPrincipalName": "MeganB@M365x214355.onmicrosoft.com", - "birthDay": "2017-09-04", + "birthDay": "1999-08-07", "id": "48d31887-5fad-4d73-a9f5-3c356e68a038" }'''; @@ -58,7 +60,7 @@ const _testStudentJson = r''' "endWorkTime": "17:00:00.0000000", "userPrincipalName": "MeganB@M365x214355.onmicrosoft.com", "birthDay": "2017-09-04", - "enrolmentDate": "2017-09-04, + "enrolmentDate": "2017-09-04", "id": "48d31887-5fad-4d73-a9f5-3c356e68a038" }'''; @@ -125,17 +127,29 @@ void main() { // expect(testEntity.AdditionalData.ContainsKey('mobilePhone'), isTrue); // expect('Auditor', testEntity.additionalData['jobTitle']); expect(testEntity.id, '48d31887-5fad-4d73-a9f5-3c356e68a038'); - // expect.Equal(TestEnum.One | TestEnum.Two, + // expect(testEntity.numbers, TestEnum.One | TestEnum.Two); // expect.teststEntity.Numbers); // Unknown enum value is not included - // expect.Equal(TestNamingEnum.Item2SubItem1, - // testEntity.TestNamingEnum); // correct value is chosen - // expect.Equal(TimeSpan.FromHours(1), - // testEntity.WorkDuration); // Parses timespan values + expect(testEntity.testNamingEnum, NamingEnum.item2SubItem1); + expect(testEntity.workDuration, const Duration(hours: 1)); // expect.Equal(new Time(8, 0, 0).ToString(), // testEntity.StartWorkTime.ToString()); // Parses time values // expect.Equal(new Time(17, 0, 0).ToString(), // testEntity.EndWorkTime.ToString()); // Parses time values - expect(testEntity.birthDay, DateOnly.fromComponents(2017, 9, 4)); + expect(testEntity.birthDay, DateOnly.fromComponents(1999, 8, 7)); + } + }); + + test('Get object derived from user', () { + final jsonParseNode = JsonParseNode(jsonDecode(_testStudentJson)); + final testEntity = jsonParseNode + .getObjectValue(MicrosoftGraphUser.createFromDiscriminator); + expect(testEntity, isNotNull); + if (testEntity is DerivedMicrosoftGraphUser) { + expect(testEntity.enrolmentDate, DateOnly.fromComponents(2017, 9, 4)); + } else { + throw ApiException( + message: + 'Test entity is not of type DerivedMicrosoftGraphUser, but of ${testEntity.runtimeType}',); } }); }); diff --git a/packages/kiota_serialization_json/test/microsoft_graph_user.dart b/packages/kiota_serialization_json/test/microsoft_graph_user.dart index 6e1ee87..645a580 100644 --- a/packages/kiota_serialization_json/test/microsoft_graph_user.dart +++ b/packages/kiota_serialization_json/test/microsoft_graph_user.dart @@ -1,9 +1,13 @@ import 'package:kiota_abstractions/kiota_abstractions.dart'; import 'derived_microsoft_graph_user.dart'; +import 'test_enums.dart'; -class MicrosoftGraphUser - extends Parsable /* implements AdditionDataHolder */ { +NamingEnum? _namingEnumFactory(String value) => NamingEnum.values + .cast() + .firstWhere((e) => e!.text == value, orElse: () => null); + +class MicrosoftGraphUser extends Parsable /* implements AdditionDataHolder */ { MicrosoftGraphUser(); factory MicrosoftGraphUser.createFromDiscriminator(ParseNode parseNode) { @@ -20,11 +24,12 @@ class MicrosoftGraphUser // IDictionary AdditionalData { get; set; } String? id; // TestEnum? Numbers { get; set; } - // TestNamingEnum? TestNamingEnum { get; set; } + NamingEnum? testNamingEnum; // TimeSpan? WorkDuration { get; set; } DateOnly? birthDay; TimeOnly? startWorkTime; TimeOnly? endWorkTime; + Duration? workDuration; // DateTimeOffset? CreatedDateTime { get; set; } double? heightInMetres; String? officeLocation; @@ -37,7 +42,7 @@ class MicrosoftGraphUser // writer.writeEnumValue("testNamingEnum", TestNamingEnum); // writer.writeDateTimeOffsetValue("createdDateTime", CreatedDateTime); ..writeStringValue('officeLocation', officeLocation) - // writer.writeTimeSpanValue("workDuration", WorkDuration); + ..writeDurationValue('workDuration', workDuration) ..writeDateOnlyValue('birthDay', birthDay) ..writeDoubleValue('heightInMetres', heightInMetres) ..writeTimeOnlyValue('startWorkTime', startWorkTime) @@ -50,10 +55,11 @@ class MicrosoftGraphUser return { 'id': (node) => id = node.getStringValue(), // 'numbers': (node) => numbers = node.getEnumValue(), - // 'testNamingEnum': (node) => testNamingEnum = node.getEnumValue(), + 'testNamingEnum': (node) => + testNamingEnum = node.getEnumValue(_namingEnumFactory), // 'createdDateTime': (node) => createdDateTime = node.getDateTimeOffsetValue(); 'officeLocation': (node) => officeLocation = node.getStringValue(), - // 'workDuration': (node) => workDuration = node.getTimeSpanValue(), + 'workDuration': (node) => workDuration = node.getDurationValue(), 'heightInMetres': (node) => heightInMetres = node.getDoubleValue(), 'birthDay': (node) => birthDay = node.getDateOnlyValue(), 'startWorkTime': (node) => startWorkTime = node.getTimeOnlyValue(), diff --git a/packages/kiota_serialization_json/test/test_enums.dart b/packages/kiota_serialization_json/test/test_enums.dart new file mode 100644 index 0000000..fb2dbf5 --- /dev/null +++ b/packages/kiota_serialization_json/test/test_enums.dart @@ -0,0 +1,26 @@ +enum NumbersEnum { one, two, four, eight, sixteen } + +enum NumbersWithValueEnum { + one(0x00000001), + two(0x00000002), + four(0x00000004), + eight(0x00000008), + sixteen(0x00000010); + + const NumbersWithValueEnum(this.idx); + + final int idx; + + int get idxValue => idx; +} + +enum NamingEnum { + item1, + item2SubItem1.withText('Item2:SubItem1'), + item3SubItem1.withText('Item3:SubItem1'); + + const NamingEnum() : text = ''; + const NamingEnum.withText(this.text); + + final String text; +} From ff12902e88caacf3d247ba409dac1d175b646b80 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Fri, 23 Aug 2024 14:28:24 +0200 Subject: [PATCH 03/69] json Added support for Duartion and DateTime --- .../test/json_parse_node_test.dart | 15 +++++++-------- .../test/microsoft_graph_user.dart | 7 +++---- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/kiota_serialization_json/test/json_parse_node_test.dart b/packages/kiota_serialization_json/test/json_parse_node_test.dart index 93b79e2..31a1430 100644 --- a/packages/kiota_serialization_json/test/json_parse_node_test.dart +++ b/packages/kiota_serialization_json/test/json_parse_node_test.dart @@ -127,14 +127,12 @@ void main() { // expect(testEntity.AdditionalData.ContainsKey('mobilePhone'), isTrue); // expect('Auditor', testEntity.additionalData['jobTitle']); expect(testEntity.id, '48d31887-5fad-4d73-a9f5-3c356e68a038'); - // expect(testEntity.numbers, TestEnum.One | TestEnum.Two); - // expect.teststEntity.Numbers); // Unknown enum value is not included + // expect(testEntity.Numbers, TestEnum.One | TestEnum.Two); // Unknown enum value is not included expect(testEntity.testNamingEnum, NamingEnum.item2SubItem1); expect(testEntity.workDuration, const Duration(hours: 1)); - // expect.Equal(new Time(8, 0, 0).ToString(), - // testEntity.StartWorkTime.ToString()); // Parses time values - // expect.Equal(new Time(17, 0, 0).ToString(), - // testEntity.EndWorkTime.ToString()); // Parses time values + expect(testEntity.startWorkTime, TimeOnly.fromComponents(8, 0)); + expect(testEntity.endWorkTime, TimeOnly.fromComponents(17, 0)); + expect(testEntity.createdDateTime, DateTime.utc(2017, 7, 29, 3, 7, 25)); expect(testEntity.birthDay, DateOnly.fromComponents(1999, 8, 7)); } }); @@ -148,8 +146,9 @@ void main() { expect(testEntity.enrolmentDate, DateOnly.fromComponents(2017, 9, 4)); } else { throw ApiException( - message: - 'Test entity is not of type DerivedMicrosoftGraphUser, but of ${testEntity.runtimeType}',); + message: + 'Test entity is not of type DerivedMicrosoftGraphUser, but of ${testEntity.runtimeType}', + ); } }); }); diff --git a/packages/kiota_serialization_json/test/microsoft_graph_user.dart b/packages/kiota_serialization_json/test/microsoft_graph_user.dart index 645a580..df231f5 100644 --- a/packages/kiota_serialization_json/test/microsoft_graph_user.dart +++ b/packages/kiota_serialization_json/test/microsoft_graph_user.dart @@ -25,12 +25,11 @@ class MicrosoftGraphUser extends Parsable /* implements AdditionDataHolder */ { String? id; // TestEnum? Numbers { get; set; } NamingEnum? testNamingEnum; - // TimeSpan? WorkDuration { get; set; } DateOnly? birthDay; TimeOnly? startWorkTime; TimeOnly? endWorkTime; Duration? workDuration; - // DateTimeOffset? CreatedDateTime { get; set; } + DateTime? createdDateTime; double? heightInMetres; String? officeLocation; @@ -40,7 +39,7 @@ class MicrosoftGraphUser extends Parsable /* implements AdditionDataHolder */ { ..writeStringValue('id', id) // writer.writeEnumValue("numbers", Numbers); // writer.writeEnumValue("testNamingEnum", TestNamingEnum); - // writer.writeDateTimeOffsetValue("createdDateTime", CreatedDateTime); + ..writeDateTimeValue('createdDateTime', createdDateTime) ..writeStringValue('officeLocation', officeLocation) ..writeDurationValue('workDuration', workDuration) ..writeDateOnlyValue('birthDay', birthDay) @@ -57,7 +56,7 @@ class MicrosoftGraphUser extends Parsable /* implements AdditionDataHolder */ { // 'numbers': (node) => numbers = node.getEnumValue(), 'testNamingEnum': (node) => testNamingEnum = node.getEnumValue(_namingEnumFactory), - // 'createdDateTime': (node) => createdDateTime = node.getDateTimeOffsetValue(); + 'createdDateTime': (node) => createdDateTime = node.getDateTimeValue(), 'officeLocation': (node) => officeLocation = node.getStringValue(), 'workDuration': (node) => workDuration = node.getDurationValue(), 'heightInMetres': (node) => heightInMetres = node.getDoubleValue(), From 21e05e33e1c723ec2dd2bd87494099dcdfa3b2b8 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Mon, 26 Aug 2024 08:59:09 +0200 Subject: [PATCH 04/69] json getCollectionOfPrimitiveValues naive implementation --- .../kiota_serialization_json/lib/src/json_parse_node.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index 63edd3e..d17e79b 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -51,7 +51,12 @@ class JsonParseNode implements ParseNode { @override Iterable getCollectionOfPrimitiveValues() { - return []; + final result = []; + if (_node is List) { + _node.forEach((value) => result.add(value as T)); + } + + return result; } @override From d93ef021f0a039776d812cd709e4d1bddb8778c2 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Tue, 27 Aug 2024 09:58:46 +0200 Subject: [PATCH 05/69] json First two unit tests work Additional data is supported plus duration, date and time. (de)Serilization is by no means complete but good enough to start generating code. We will generate code for a simple client that gets version informationof an app. --- .../serialization/additional_data_holder.dart | 4 +- .../lib/src/form_parse_node.dart | 2 +- .../lib/src/json_parse_node.dart | 37 ++++++++++++------- .../test/json_parse_node_test.dart | 18 ++++----- .../test/microsoft_graph_user.dart | 35 +++++++++++------- .../test/test_enums.dart | 27 +++----------- 6 files changed, 62 insertions(+), 61 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/serialization/additional_data_holder.dart b/packages/kiota_abstractions/lib/src/serialization/additional_data_holder.dart index 9b6640e..f9794a7 100644 --- a/packages/kiota_abstractions/lib/src/serialization/additional_data_holder.dart +++ b/packages/kiota_abstractions/lib/src/serialization/additional_data_holder.dart @@ -2,7 +2,7 @@ part of '../../kiota_abstractions.dart'; /// Defines a contract for models that can hold additional data besides the /// properties defined in the model. -abstract class AdditionDataHolder { +abstract class AdditionalDataHolder { /// Additional data that is not part of the model's properties. - Map additionalData = {}; + Map additionalData = {}; } diff --git a/packages/kiota_serialization_form/lib/src/form_parse_node.dart b/packages/kiota_serialization_form/lib/src/form_parse_node.dart index dea5fe2..cb28404 100644 --- a/packages/kiota_serialization_form/lib/src/form_parse_node.dart +++ b/packages/kiota_serialization_form/lib/src/form_parse_node.dart @@ -219,7 +219,7 @@ class FormParseNode implements ParseNode { } Map? additionalData; - if (item case final AdditionDataHolder dataHolder) { + if (item case final AdditionalDataHolder dataHolder) { dataHolder.additionalData = additionalData ??= {}; } diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index d17e79b..0305128 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -26,15 +26,13 @@ class JsonParseNode implements ParseNode { if (_node is Map) { final childNode = _node[identifier]; if (childNode != null) { - final result = JsonParseNode(childNode); - // TODO(Kees): Call on... events - // result.onBeforeAssignFieldValues((f) => onBeforeAssignFieldValues); - // result.onAfterAssignFieldValues(onAfterAssignFieldValues); - return result; + return JsonParseNode(childNode) + ..onBeforeAssignFieldValues = onBeforeAssignFieldValues + ..onAfterAssignFieldValues = onAfterAssignFieldValues; } - - return null; } + + return null; } @override @@ -51,11 +49,11 @@ class JsonParseNode implements ParseNode { @override Iterable getCollectionOfPrimitiveValues() { - final result = []; + final result = []; if (_node is List) { _node.forEach((value) => result.add(value as T)); } - + return result; } @@ -106,16 +104,29 @@ class JsonParseNode implements ParseNode { } void _assignFieldValues(T item) { - final fieldDeserializers = item.getFieldDeserializers(); - if (_node is Map) { + onBeforeAssignFieldValues?.call(item); + + final itemAdditionalData = item is AdditionalDataHolder + ? (item as AdditionalDataHolder).additionalData + : null; + + final fieldDeserializers = item.getFieldDeserializers(); + for (final entry in _node.entries) { if (fieldDeserializers.containsKey(entry.key)) { - print('Found property: ${entry.key} to deserialize'); final fieldDeserializer = fieldDeserializers[entry.key]; - fieldDeserializer!.call(JsonParseNode(entry.value)); + if (fieldDeserializer != null) { + final itemNode = JsonParseNode(entry.value) + ..onBeforeAssignFieldValues = onBeforeAssignFieldValues + ..onAfterAssignFieldValues = onAfterAssignFieldValues; + fieldDeserializer.call(itemNode); + } + } else { + itemAdditionalData?[entry.key as String] = entry.value; } } + onAfterAssignFieldValues?.call(item); } } diff --git a/packages/kiota_serialization_json/test/json_parse_node_test.dart b/packages/kiota_serialization_json/test/json_parse_node_test.dart index 31a1430..7441a3d 100644 --- a/packages/kiota_serialization_json/test/json_parse_node_test.dart +++ b/packages/kiota_serialization_json/test/json_parse_node_test.dart @@ -16,8 +16,7 @@ const _testUserJson = r''' "+1 412 555 0109" ], "displayName": "Megan Bowen", - "numbers": "one,two,thirtytwo", - "testNamingEnum": "Item2:SubItem1", + "namingEnum": "Item2:SubItem1", "givenName": "Megan", "accountEnabled": true, "createdDateTime": "2017-07-29T03:07:25Z", @@ -44,8 +43,7 @@ const _testStudentJson = r''' "+1 412 555 0109" ], "displayName": "Megan Bowen", - "numbers": "one,two,thirtytwo", - "testNamingEnum": "Item2:SubItem1", + "namingEnum": "Item2:SubItem1", "givenName": "Megan", "accountEnabled": true, "createdDateTime": "2017-07-29T03:07:25Z", @@ -119,16 +117,16 @@ void main() { final testEntity = jsonParseNode .getObjectValue(MicrosoftGraphUser.createFromDiscriminator); + print(testEntity); expect(testEntity, isNotNull); if (testEntity != null) { + expect(testEntity.additionalData, isNotEmpty); + expect(testEntity.additionalData.containsKey('mobilePhone'), isTrue); + expect(testEntity.additionalData['jobTitle'], 'Auditor'); + expect(testEntity.officeLocation, null); - // expect(testEntity.additionalData, isNotEmpty); - // expect(testEntity.additionalData.containsKey('jobTitle'), isTrue); - // expect(testEntity.AdditionalData.ContainsKey('mobilePhone'), isTrue); - // expect('Auditor', testEntity.additionalData['jobTitle']); expect(testEntity.id, '48d31887-5fad-4d73-a9f5-3c356e68a038'); - // expect(testEntity.Numbers, TestEnum.One | TestEnum.Two); // Unknown enum value is not included - expect(testEntity.testNamingEnum, NamingEnum.item2SubItem1); + expect(testEntity.namingEnum, NamingEnum.item2SubItem1); expect(testEntity.workDuration, const Duration(hours: 1)); expect(testEntity.startWorkTime, TimeOnly.fromComponents(8, 0)); expect(testEntity.endWorkTime, TimeOnly.fromComponents(17, 0)); diff --git a/packages/kiota_serialization_json/test/microsoft_graph_user.dart b/packages/kiota_serialization_json/test/microsoft_graph_user.dart index df231f5..dd2d318 100644 --- a/packages/kiota_serialization_json/test/microsoft_graph_user.dart +++ b/packages/kiota_serialization_json/test/microsoft_graph_user.dart @@ -5,9 +5,11 @@ import 'test_enums.dart'; NamingEnum? _namingEnumFactory(String value) => NamingEnum.values .cast() - .firstWhere((e) => e!.text == value, orElse: () => null); + .firstWhere((e) => e!.value == value, orElse: () => null); -class MicrosoftGraphUser extends Parsable /* implements AdditionDataHolder */ { +String? _namingEnumSerializer(NamingEnum? value) => value?.value; + +class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { MicrosoftGraphUser(); factory MicrosoftGraphUser.createFromDiscriminator(ParseNode parseNode) { @@ -21,10 +23,11 @@ class MicrosoftGraphUser extends Parsable /* implements AdditionDataHolder */ { }; } - // IDictionary AdditionalData { get; set; } + @override + Map additionalData = {}; + String? id; - // TestEnum? Numbers { get; set; } - NamingEnum? testNamingEnum; + NamingEnum? namingEnum; DateOnly? birthDay; TimeOnly? startWorkTime; TimeOnly? endWorkTime; @@ -37,25 +40,24 @@ class MicrosoftGraphUser extends Parsable /* implements AdditionDataHolder */ { void serialize(SerializationWriter writer) { writer ..writeStringValue('id', id) - // writer.writeEnumValue("numbers", Numbers); - // writer.writeEnumValue("testNamingEnum", TestNamingEnum); + ..writeEnumValue( + 'namingEnum', namingEnum, _namingEnumSerializer) ..writeDateTimeValue('createdDateTime', createdDateTime) ..writeStringValue('officeLocation', officeLocation) ..writeDurationValue('workDuration', workDuration) ..writeDateOnlyValue('birthDay', birthDay) ..writeDoubleValue('heightInMetres', heightInMetres) ..writeTimeOnlyValue('startWorkTime', startWorkTime) - ..writeTimeOnlyValue('endWorkTime', endWorkTime); - // writer.writeAdditionalData(AdditionalData); + ..writeTimeOnlyValue('endWorkTime', endWorkTime) + ..writeAdditionalData(additionalData); } @override Map getFieldDeserializers() { return { 'id': (node) => id = node.getStringValue(), - // 'numbers': (node) => numbers = node.getEnumValue(), - 'testNamingEnum': (node) => - testNamingEnum = node.getEnumValue(_namingEnumFactory), + 'namingEnum': (node) => + namingEnum = node.getEnumValue(_namingEnumFactory), 'createdDateTime': (node) => createdDateTime = node.getDateTimeValue(), 'officeLocation': (node) => officeLocation = node.getStringValue(), 'workDuration': (node) => workDuration = node.getDurationValue(), @@ -70,8 +72,15 @@ class MicrosoftGraphUser extends Parsable /* implements AdditionDataHolder */ { String toString() { return ''' id: $id - birthDay: $birthDay + namingEnum: $namingEnum + createdDateTime: $createdDateTime officeLocation: $officeLocation + workDuration: $workDuration + heightInMetres: $heightInMetres + birthDay: ${birthDay?.year}-${birthDay?.month}-${birthDay?.day} + startWorkTime: ${startWorkTime?.hours}:${startWorkTime?.minutes} + endWorkTime: ${endWorkTime?.hours}:${endWorkTime?.minutes} + additionalData: $additionalData '''; } } diff --git a/packages/kiota_serialization_json/test/test_enums.dart b/packages/kiota_serialization_json/test/test_enums.dart index fb2dbf5..8c6b07e 100644 --- a/packages/kiota_serialization_json/test/test_enums.dart +++ b/packages/kiota_serialization_json/test/test_enums.dart @@ -1,26 +1,9 @@ -enum NumbersEnum { one, two, four, eight, sixteen } - -enum NumbersWithValueEnum { - one(0x00000001), - two(0x00000002), - four(0x00000004), - eight(0x00000008), - sixteen(0x00000010); - - const NumbersWithValueEnum(this.idx); - - final int idx; - - int get idxValue => idx; -} - enum NamingEnum { - item1, - item2SubItem1.withText('Item2:SubItem1'), - item3SubItem1.withText('Item3:SubItem1'); + item1.withValue(null), + item2SubItem1.withValue('Item2:SubItem1'), + item3SubItem1.withValue('Item3:SubItem1'); - const NamingEnum() : text = ''; - const NamingEnum.withText(this.text); + const NamingEnum.withValue(this.value); - final String text; + final String? value; } From a57d00ad8fa07084500afdfb940d2f577d3cd709 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Tue, 17 Sep 2024 12:56:01 +0200 Subject: [PATCH 06/69] Changed baseUrl to baseurl As it looks like the lower case version is used everywhere including in other languages than Dart. --- packages/kiota_http/lib/src/http_client_request_adapter.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kiota_http/lib/src/http_client_request_adapter.dart b/packages/kiota_http/lib/src/http_client_request_adapter.dart index 44b600f..c30378b 100644 --- a/packages/kiota_http/lib/src/http_client_request_adapter.dart +++ b/packages/kiota_http/lib/src/http_client_request_adapter.dart @@ -80,7 +80,7 @@ class HttpClientRequestAdapter implements RequestAdapter { } void _setBaseUrl(RequestInformation requestInfo) { - requestInfo.pathParameters['baseUrl'] = baseUrl; + requestInfo.pathParameters['baseurl'] = baseUrl; } ResponseHandler? _getResponseHandler(RequestInformation requestInfo) { From b04a39e1270bbec03841f5e57e6b538ece38673f Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 17 Sep 2024 14:49:10 +0200 Subject: [PATCH 07/69] Use correct contenttype --- .../lib/src/serialization/parse_node_factory_registry.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/serialization/parse_node_factory_registry.dart b/packages/kiota_abstractions/lib/src/serialization/parse_node_factory_registry.dart index a079989..a6962b2 100644 --- a/packages/kiota_abstractions/lib/src/serialization/parse_node_factory_registry.dart +++ b/packages/kiota_abstractions/lib/src/serialization/parse_node_factory_registry.dart @@ -35,14 +35,14 @@ class ParseNodeFactoryRegistry implements ParseNodeFactory { contentType.split(';').where((element) => element.isNotEmpty).first; if (contentTypeAssociatedFactories.containsKey(vendorSpecificContentType)) { return contentTypeAssociatedFactories[vendorSpecificContentType]! - .getRootParseNode(contentType, content); + .getRootParseNode(vendorSpecificContentType, content); } final cleanedContentType = vendorSpecificContentType.replaceAll(contentTypeVendorCleanupRegex, ''); if (contentTypeAssociatedFactories.containsKey(cleanedContentType)) { return contentTypeAssociatedFactories[cleanedContentType]! - .getRootParseNode(contentType, content); + .getRootParseNode(cleanedContentType, content); } throw UnsupportedError( From f1b3546401bed98ae45239e45b623853aaaba527 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 18 Sep 2024 14:40:42 +0200 Subject: [PATCH 08/69] Added generics to requestconfiguration --- .../kiota_abstractions/lib/kiota_abstractions.dart | 2 ++ .../lib/src/abstract_query_parameters.dart | 6 ++++++ .../lib/src/default_query_parameters.dart | 11 +++++++++++ .../extensions/request_information_extensions.dart | 6 +++--- .../lib/src/request_configuration.dart | 4 ++-- 5 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 packages/kiota_abstractions/lib/src/abstract_query_parameters.dart create mode 100644 packages/kiota_abstractions/lib/src/default_query_parameters.dart diff --git a/packages/kiota_abstractions/lib/kiota_abstractions.dart b/packages/kiota_abstractions/lib/kiota_abstractions.dart index 1e37477..71b1f3e 100644 --- a/packages/kiota_abstractions/lib/kiota_abstractions.dart +++ b/packages/kiota_abstractions/lib/kiota_abstractions.dart @@ -15,6 +15,7 @@ import 'package:meta/meta.dart'; import 'package:std_uritemplate/std_uritemplate.dart'; import 'package:uuid/uuid.dart'; +part 'src/abstract_query_parameters.dart'; part 'src/api_client_builder.dart'; part 'src/api_exception.dart'; part 'src/authentication/access_token_provider.dart'; @@ -27,6 +28,7 @@ part 'src/authentication/base_bearer_token_authentication_provider.dart'; part 'src/base_request_builder.dart'; part 'src/case_insensitive_map.dart'; part 'src/date_only.dart'; +part 'src/default_query_parameters.dart'; part 'src/error_mappings.dart'; part 'src/extensions/base_request_builder_extensions.dart'; part 'src/extensions/date_only_extensions.dart'; diff --git a/packages/kiota_abstractions/lib/src/abstract_query_parameters.dart b/packages/kiota_abstractions/lib/src/abstract_query_parameters.dart new file mode 100644 index 0000000..35da492 --- /dev/null +++ b/packages/kiota_abstractions/lib/src/abstract_query_parameters.dart @@ -0,0 +1,6 @@ +part of '../kiota_abstractions.dart'; + +/// Type definition for query parameters. +abstract class AbstractQueryParameters{ + Map getQueryParameters(); +} diff --git a/packages/kiota_abstractions/lib/src/default_query_parameters.dart b/packages/kiota_abstractions/lib/src/default_query_parameters.dart new file mode 100644 index 0000000..f3f4c34 --- /dev/null +++ b/packages/kiota_abstractions/lib/src/default_query_parameters.dart @@ -0,0 +1,11 @@ +part of '../kiota_abstractions.dart'; + +/// Type definition for query parameters. +class DefaultQueryParameters extends AbstractQueryParameters{ + Map queryParameters = {}; + + @override + Map getQueryParameters(){ + return queryParameters; + } +} diff --git a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart index 88d84f2..7d3a07f 100644 --- a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart +++ b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart @@ -137,16 +137,16 @@ extension RequestInformationExtensions on RequestInformation { content = writer.getSerializedContent(); } - void configure(void Function(RequestConfiguration)? configurator) { + void configure(void Function(RequestConfiguration)? configurator) { if (configurator == null) { return; } - final config = RequestConfiguration(); + final config = RequestConfiguration(); configurator(config); - addQueryParameters(config.queryParameters); + addQueryParameters(config.queryParameters.getQueryParameters()); addHeaders(config.headers); addRequestOptions(config.options); } diff --git a/packages/kiota_abstractions/lib/src/request_configuration.dart b/packages/kiota_abstractions/lib/src/request_configuration.dart index e746750..da5b87a 100644 --- a/packages/kiota_abstractions/lib/src/request_configuration.dart +++ b/packages/kiota_abstractions/lib/src/request_configuration.dart @@ -1,7 +1,7 @@ part of '../kiota_abstractions.dart'; /// Request configuration type for [BaseRequestBuilder]s. -class RequestConfiguration { +class RequestConfiguration { /// The HTTP headers of the request. HttpHeaders headers = HttpHeaders(); @@ -9,5 +9,5 @@ class RequestConfiguration { List options = []; /// The request query parameters. - Map queryParameters = {}; + late T queryParameters; } From 6e43b5a4dc33b011c6379c584a1599af37936bac Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 18 Sep 2024 15:39:31 +0200 Subject: [PATCH 09/69] Additional functions for configure method --- .../lib/src/extensions/request_information_extensions.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart index 7d3a07f..a41b4d2 100644 --- a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart +++ b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart @@ -137,7 +137,7 @@ extension RequestInformationExtensions on RequestInformation { content = writer.getSerializedContent(); } - void configure(void Function(RequestConfiguration)? configurator) { + void configure(void Function(RequestConfiguration)? configurator, T Function() createParameters, void Function(T) parameterValues) { if (configurator == null) { return; } @@ -145,8 +145,9 @@ extension RequestInformationExtensions on RequestInformation { final config = RequestConfiguration(); configurator(config); - - addQueryParameters(config.queryParameters.getQueryParameters()); + final typedParameters = createParameters(); + parameterValues(typedParameters); + addQueryParameters(typedParameters.getQueryParameters()); addHeaders(config.headers); addRequestOptions(config.options); } From e16651e971590208da9f25bfcd4be2ef15d64695 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Thu, 19 Sep 2024 07:55:26 +0200 Subject: [PATCH 10/69] remove parameters here --- packages/kiota_abstractions/lib/src/request_configuration.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/request_configuration.dart b/packages/kiota_abstractions/lib/src/request_configuration.dart index da5b87a..85c7334 100644 --- a/packages/kiota_abstractions/lib/src/request_configuration.dart +++ b/packages/kiota_abstractions/lib/src/request_configuration.dart @@ -7,7 +7,4 @@ class RequestConfiguration { /// The request options. List options = []; - - /// The request query parameters. - late T queryParameters; } From 969733885e4284e64975d97642cf1a4c0620a938 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Thu, 19 Sep 2024 09:30:57 +0200 Subject: [PATCH 11/69] Use less parameters for method --- .../extensions/request_information_extensions.dart | 11 +++++------ .../lib/src/request_configuration.dart | 2 ++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart index a41b4d2..7350f4a 100644 --- a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart +++ b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart @@ -137,17 +137,16 @@ extension RequestInformationExtensions on RequestInformation { content = writer.getSerializedContent(); } - void configure(void Function(RequestConfiguration)? configurator, T Function() createParameters, void Function(T) parameterValues) { + void configure(void Function(RequestConfiguration)? configurator, T Function() createParameters) { if (configurator == null) { return; } - final config = RequestConfiguration(); - + final config = RequestConfiguration() + ..queryParameters = createParameters(); configurator(config); - final typedParameters = createParameters(); - parameterValues(typedParameters); - addQueryParameters(typedParameters.getQueryParameters()); + + addQueryParameters(config.queryParameters.getQueryParameters()); addHeaders(config.headers); addRequestOptions(config.options); } diff --git a/packages/kiota_abstractions/lib/src/request_configuration.dart b/packages/kiota_abstractions/lib/src/request_configuration.dart index 85c7334..4a448d9 100644 --- a/packages/kiota_abstractions/lib/src/request_configuration.dart +++ b/packages/kiota_abstractions/lib/src/request_configuration.dart @@ -7,4 +7,6 @@ class RequestConfiguration { /// The request options. List options = []; + + late T queryParameters; } From 23b8f150c36c32cc14a19fafa2c8965a3626dc9b Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Fri, 20 Sep 2024 07:39:19 +0200 Subject: [PATCH 12/69] Not ignoring the version.dart file anymore Previously we had to manually copy the version.dart file in our .pub-cache folder. --- .gitignore | 5 ++++- packages/kiota_http/lib/gen/version.dart | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 packages/kiota_http/lib/gen/version.dart diff --git a/.gitignore b/.gitignore index 7e89509..312f797 100644 --- a/.gitignore +++ b/.gitignore @@ -29,8 +29,11 @@ pubspec.lock build/ # ignore generated files -gen/ +**/gen/** */ *.mocks.dart +# Do not ignore generated version +!**/gen/version.dart + # Licenses for packages are not checked in; they are copied from the root packages/*/LICENSE diff --git a/packages/kiota_http/lib/gen/version.dart b/packages/kiota_http/lib/gen/version.dart new file mode 100644 index 0000000..1aa2f1b --- /dev/null +++ b/packages/kiota_http/lib/gen/version.dart @@ -0,0 +1,2 @@ +// Generated code. Do not modify. +const packageVersion = '0.0.1-pre.1'; From 19e8411b5f204880742238e78d2c5a39719e7788 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Fri, 20 Sep 2024 08:01:46 +0200 Subject: [PATCH 13/69] Corrected ignoring gen folder --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 312f797..9312c58 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,7 @@ pubspec.lock build/ # ignore generated files -**/gen/** */ +**/gen/** *.mocks.dart # Do not ignore generated version From e7d0d0b597e669da8059b9975b7bc7cb83e4790c Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Fri, 20 Sep 2024 08:11:45 +0200 Subject: [PATCH 14/69] Copied version.dart since I could not get it to work @Ricardo. I tried to not ignore the verion.dart file in .gitignore But it ignored it anyway. I know this is not a good solution that I will have to fix later. --- packages/kiota_http/lib/kiota_http.dart | 2 +- packages/kiota_http/lib/version.dart | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 packages/kiota_http/lib/version.dart diff --git a/packages/kiota_http/lib/kiota_http.dart b/packages/kiota_http/lib/kiota_http.dart index fd8bd9a..d288cac 100644 --- a/packages/kiota_http/lib/kiota_http.dart +++ b/packages/kiota_http/lib/kiota_http.dart @@ -7,7 +7,7 @@ import 'dart:typed_data'; import 'package:http/http.dart' as http; import 'package:http/retry.dart' as retry; import 'package:kiota_abstractions/kiota_abstractions.dart'; -import 'package:kiota_http/gen/version.dart'; +import 'package:kiota_http/version.dart'; import 'package:uuid/uuid.dart'; part 'src/http_client_request_adapter.dart'; diff --git a/packages/kiota_http/lib/version.dart b/packages/kiota_http/lib/version.dart new file mode 100644 index 0000000..1aa2f1b --- /dev/null +++ b/packages/kiota_http/lib/version.dart @@ -0,0 +1,2 @@ +// Generated code. Do not modify. +const packageVersion = '0.0.1-pre.1'; From 76102a3ea49551494b81848e0b73aec5831fa5b4 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Fri, 20 Sep 2024 08:20:36 +0200 Subject: [PATCH 15/69] Still trying to get a version.dart --- packages/kiota_http/lib/kiota_http.dart | 2 +- packages/kiota_http/lib/{ => src}/version.dart | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/kiota_http/lib/{ => src}/version.dart (100%) diff --git a/packages/kiota_http/lib/kiota_http.dart b/packages/kiota_http/lib/kiota_http.dart index d288cac..4119342 100644 --- a/packages/kiota_http/lib/kiota_http.dart +++ b/packages/kiota_http/lib/kiota_http.dart @@ -7,7 +7,7 @@ import 'dart:typed_data'; import 'package:http/http.dart' as http; import 'package:http/retry.dart' as retry; import 'package:kiota_abstractions/kiota_abstractions.dart'; -import 'package:kiota_http/version.dart'; +import 'package:kiota_http/src/version.dart'; import 'package:uuid/uuid.dart'; part 'src/http_client_request_adapter.dart'; diff --git a/packages/kiota_http/lib/version.dart b/packages/kiota_http/lib/src/version.dart similarity index 100% rename from packages/kiota_http/lib/version.dart rename to packages/kiota_http/lib/src/version.dart From 4b09f1372c0d909acd1a1822c0f538511435bd6d Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Fri, 20 Sep 2024 09:05:00 +0200 Subject: [PATCH 16/69] Looks like it works with the xorrect version.dart file now. --- packages/kiota_http/lib/src/version.dart | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 packages/kiota_http/lib/src/version.dart diff --git a/packages/kiota_http/lib/src/version.dart b/packages/kiota_http/lib/src/version.dart deleted file mode 100644 index 1aa2f1b..0000000 --- a/packages/kiota_http/lib/src/version.dart +++ /dev/null @@ -1,2 +0,0 @@ -// Generated code. Do not modify. -const packageVersion = '0.0.1-pre.1'; From 371c950d34e8af47846d3de4ee3d7ddb5278b8d7 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Fri, 20 Sep 2024 09:06:22 +0200 Subject: [PATCH 17/69] Reverting changes Code seems to work with correct version.dart file. --- packages/kiota_http/lib/kiota_http.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kiota_http/lib/kiota_http.dart b/packages/kiota_http/lib/kiota_http.dart index 4119342..fd8bd9a 100644 --- a/packages/kiota_http/lib/kiota_http.dart +++ b/packages/kiota_http/lib/kiota_http.dart @@ -7,7 +7,7 @@ import 'dart:typed_data'; import 'package:http/http.dart' as http; import 'package:http/retry.dart' as retry; import 'package:kiota_abstractions/kiota_abstractions.dart'; -import 'package:kiota_http/src/version.dart'; +import 'package:kiota_http/gen/version.dart'; import 'package:uuid/uuid.dart'; part 'src/http_client_request_adapter.dart'; From cbc8d3fe7f06fac884940d68cb9aced83ec512bf Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 24 Sep 2024 08:58:52 +0200 Subject: [PATCH 18/69] Implement getCollectionOfObjectValues and getCollectionOfEnumValues --- .../lib/src/json_parse_node.dart | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index 0305128..d5dee30 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -37,14 +37,29 @@ class JsonParseNode implements ParseNode { @override Iterable getCollectionOfEnumValues(EnumFactory parser) { - return []; + final result = []; + if (_node is List) { + _node.forEach((value) => result.add(parser(_node.toString())!)); + } + + return result; } @override Iterable getCollectionOfObjectValues( ParsableFactory factory, ) { - return []; + final result = []; + if (_node is List) { + for (final value in _node) + { + final node = JsonParseNode(value) + ..onAfterAssignFieldValues = onAfterAssignFieldValues + ..onBeforeAssignFieldValues = onBeforeAssignFieldValues; + result.add(factory(node)); + } + } + return result; } @override From e885bbdeefd4e387bda1b4690cf4433b6f14af92 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 24 Sep 2024 10:46:01 +0200 Subject: [PATCH 19/69] Fixed implementation of collection methods --- .../lib/src/json_parse_node.dart | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index d5dee30..db4fe13 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -39,9 +39,13 @@ class JsonParseNode implements ParseNode { Iterable getCollectionOfEnumValues(EnumFactory parser) { final result = []; if (_node is List) { - _node.forEach((value) => result.add(parser(_node.toString())!)); + for (final value in _node) + { + final enumValue = parser(value); + if(enumValue != null) + result.add(enumValue); + } } - return result; } @@ -56,7 +60,9 @@ class JsonParseNode implements ParseNode { final node = JsonParseNode(value) ..onAfterAssignFieldValues = onAfterAssignFieldValues ..onBeforeAssignFieldValues = onBeforeAssignFieldValues; - result.add(factory(node)); + final objectValue = node.getObjectValue(factory); + if(objectValue != null) + result.add(objectValue); } } return result; From 7028c85609df16b685d039efe5d074f5e4409238 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 24 Sep 2024 13:20:20 +0200 Subject: [PATCH 20/69] Parse enum value as string --- .../kiota_serialization_json/lib/src/json_parse_node.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index db4fe13..ad24fa7 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -41,9 +41,10 @@ class JsonParseNode implements ParseNode { if (_node is List) { for (final value in _node) { - final enumValue = parser(value); - if(enumValue != null) + final enumValue = parser(value as String); + if(enumValue != null){ result.add(enumValue); + } } } return result; @@ -61,8 +62,9 @@ class JsonParseNode implements ParseNode { ..onAfterAssignFieldValues = onAfterAssignFieldValues ..onBeforeAssignFieldValues = onBeforeAssignFieldValues; final objectValue = node.getObjectValue(factory); - if(objectValue != null) + if(objectValue != null){ result.add(objectValue); + } } } return result; From f6c5d1fc2d74379f5298f689127aa87fb6c60a9b Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Tue, 24 Sep 2024 14:34:19 +0200 Subject: [PATCH 21/69] Used proper name for factory Solved compilation error. Oddly enough the code seemed to work with this error. --- .../kiota_serialization_json/lib/src/json_parse_node.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index db4fe13..c9c25f0 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -36,14 +36,15 @@ class JsonParseNode implements ParseNode { } @override - Iterable getCollectionOfEnumValues(EnumFactory parser) { + Iterable getCollectionOfEnumValues(EnumFactory factory) { final result = []; if (_node is List) { for (final value in _node) { - final enumValue = parser(value); - if(enumValue != null) + final enumValue = factory(value.toString()); + if(enumValue != null) { result.add(enumValue); + } } } return result; From 79122e090c49e2957b64ccf70eb6eacfe0e7a5a2 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 25 Sep 2024 07:51:49 +0200 Subject: [PATCH 22/69] Don't create copy of ApiException to throw, because then all values in subclasses of ApiException get lost --- packages/kiota_abstractions/lib/src/api_exception.dart | 4 ++-- .../kiota_http/lib/src/http_client_request_adapter.dart | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/api_exception.dart b/packages/kiota_abstractions/lib/src/api_exception.dart index 876a966..21d1903 100644 --- a/packages/kiota_abstractions/lib/src/api_exception.dart +++ b/packages/kiota_abstractions/lib/src/api_exception.dart @@ -12,13 +12,13 @@ class ApiException implements Exception { }); /// The HTTP status code of the response. - final int? statusCode; + int? statusCode; /// An optional message that describes the error. final String? message; /// The headers of the response. - final Map>? responseHeaders; + Map>? responseHeaders; /// The inner exceptions that caused this exception. final Iterable? innerExceptions; diff --git a/packages/kiota_http/lib/src/http_client_request_adapter.dart b/packages/kiota_http/lib/src/http_client_request_adapter.dart index c30378b..ac529ab 100644 --- a/packages/kiota_http/lib/src/http_client_request_adapter.dart +++ b/packages/kiota_http/lib/src/http_client_request_adapter.dart @@ -131,11 +131,9 @@ class HttpClientRequestAdapter implements RequestAdapter { final result = rootNode?.getObjectValue(errorFactory); if (result case Exception exception) { - if (exception case final ApiException apiException) { - exception = apiException.copyWith( - statusCode: statusCodeInt, - responseHeaders: headers, - ); + if (exception case final ApiException apiException) { + apiException.statusCode = statusCodeInt; + apiException.responseHeaders = headers; } throw exception; From cd3b5d130640a38e61e7b870554c92660511ae55 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Fri, 27 Sep 2024 08:42:30 +0200 Subject: [PATCH 23/69] Get correct writer for corrected content type --- .../serialization/serialization_writer_factory_registry.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/serialization/serialization_writer_factory_registry.dart b/packages/kiota_abstractions/lib/src/serialization/serialization_writer_factory_registry.dart index 3c8ec53..e67d24a 100644 --- a/packages/kiota_abstractions/lib/src/serialization/serialization_writer_factory_registry.dart +++ b/packages/kiota_abstractions/lib/src/serialization/serialization_writer_factory_registry.dart @@ -29,14 +29,14 @@ class SerializationWriterFactoryRegistry implements SerializationWriterFactory { contentType.split(';').where((element) => element.isNotEmpty).first; if (contentTypeAssociatedFactories.containsKey(vendorSpecificContentType)) { return contentTypeAssociatedFactories[vendorSpecificContentType]! - .getSerializationWriter(contentType); + .getSerializationWriter(vendorSpecificContentType); } final cleanedContentType = vendorSpecificContentType.replaceAll(contentTypeVendorCleanupRegex, ''); if (contentTypeAssociatedFactories.containsKey(cleanedContentType)) { return contentTypeAssociatedFactories[cleanedContentType]! - .getSerializationWriter(contentType); + .getSerializationWriter(cleanedContentType); } throw UnsupportedError( From 5df9b84fdd1fd1e4ab997eca5269acd832582987 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Fri, 27 Sep 2024 13:39:20 +0200 Subject: [PATCH 24/69] Initial commit for processing untyped data --- .../lib/kiota_abstractions.dart | 8 ++ .../lib/src/serialization/untyped_array.dart | 15 +++ .../src/serialization/untyped_boolean.dart | 7 ++ .../lib/src/serialization/untyped_double.dart | 7 ++ .../src/serialization/untyped_integer.dart | 7 ++ .../lib/src/serialization/untyped_node.dart | 29 ++++++ .../lib/src/serialization/untyped_null.dart | 7 ++ .../lib/src/serialization/untyped_object.dart | 8 ++ .../lib/src/serialization/untyped_string.dart | 8 ++ .../lib/src/json_parse_node.dart | 99 ++++++++++++++++--- .../test/json_parse_node_test.dart | 17 +++- .../test/untyped_test_entity.dart | 51 ++++++++++ 12 files changed, 246 insertions(+), 17 deletions(-) create mode 100644 packages/kiota_abstractions/lib/src/serialization/untyped_array.dart create mode 100644 packages/kiota_abstractions/lib/src/serialization/untyped_boolean.dart create mode 100644 packages/kiota_abstractions/lib/src/serialization/untyped_double.dart create mode 100644 packages/kiota_abstractions/lib/src/serialization/untyped_integer.dart create mode 100644 packages/kiota_abstractions/lib/src/serialization/untyped_node.dart create mode 100644 packages/kiota_abstractions/lib/src/serialization/untyped_null.dart create mode 100644 packages/kiota_abstractions/lib/src/serialization/untyped_object.dart create mode 100644 packages/kiota_abstractions/lib/src/serialization/untyped_string.dart create mode 100644 packages/kiota_serialization_json/test/untyped_test_entity.dart diff --git a/packages/kiota_abstractions/lib/kiota_abstractions.dart b/packages/kiota_abstractions/lib/kiota_abstractions.dart index 71b1f3e..9725d04 100644 --- a/packages/kiota_abstractions/lib/kiota_abstractions.dart +++ b/packages/kiota_abstractions/lib/kiota_abstractions.dart @@ -63,6 +63,14 @@ part 'src/serialization/serialization_writer.dart'; part 'src/serialization/serialization_writer_factory.dart'; part 'src/serialization/serialization_writer_factory_registry.dart'; part 'src/serialization/serialization_writer_proxy_factory.dart'; +part 'src/serialization/untyped_array.dart'; +part 'src/serialization/untyped_boolean.dart'; +part 'src/serialization/untyped_double.dart'; +part 'src/serialization/untyped_integer.dart'; +part 'src/serialization/untyped_node.dart'; +part 'src/serialization/untyped_null.dart'; +part 'src/serialization/untyped_object.dart'; +part 'src/serialization/untyped_string.dart'; part 'src/store/backed_model.dart'; part 'src/store/backing_store.dart'; part 'src/store/backing_store_factory.dart'; diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_array.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_array.dart new file mode 100644 index 0000000..89641fe --- /dev/null +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_array.dart @@ -0,0 +1,15 @@ +part of '../../kiota_abstractions.dart'; + +/// Represents an untyped node with a collection of other untyped nodes. +class UntypedArray extends UntypedNode { + + /// Constructs an instance from the supplied [collection] + UntypedArray(this.collection); + + Iterable collection; + + @override + Iterable getValue() { + return collection; + } +} diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_boolean.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_boolean.dart new file mode 100644 index 0000000..37de008 --- /dev/null +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_boolean.dart @@ -0,0 +1,7 @@ +part of '../../kiota_abstractions.dart'; + +class UntypedBoolean extends UntypedNode { + UntypedBoolean({required this.value}); + + final bool value; +} diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_double.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_double.dart new file mode 100644 index 0000000..1a26fe9 --- /dev/null +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_double.dart @@ -0,0 +1,7 @@ +part of '../../kiota_abstractions.dart'; + +class UntypedDouble extends UntypedNode { + UntypedDouble(this.value); + + final double value; +} diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_integer.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_integer.dart new file mode 100644 index 0000000..3d32fd7 --- /dev/null +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_integer.dart @@ -0,0 +1,7 @@ +part of '../../kiota_abstractions.dart'; + +class UntypedInteger extends UntypedNode { + UntypedInteger(this.value); + + final int value; +} diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart new file mode 100644 index 0000000..516dd09 --- /dev/null +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart @@ -0,0 +1,29 @@ +part of '../../kiota_abstractions.dart'; + +/// Base class for untyped node. +class UntypedNode implements Parsable { + + /// The deserialization information for the current model. + /// Returns a map of serializer methods for this object. + @override + Map getFieldDeserializers() { + return {}; + } + + /// Serializes the current object + @override + void serialize(SerializationWriter writer) { + // no properties to serialize. This is handled by custom serialization logic. + } + + /// Gets the value assigned to untyped node. + Object getValue() { + throw Exception('getValue is implemented for derived types of UntypedNode'); + } + + /// Creates a new [UntypedNode] instance of the appropriate class + /// based on discriminator value. + static UntypedNode createFromDiscriminatorValue(ParseNode parseNode) { + return UntypedNode(); + } +} diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_null.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_null.dart new file mode 100644 index 0000000..44249bf --- /dev/null +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_null.dart @@ -0,0 +1,7 @@ +part of '../../kiota_abstractions.dart'; + +class UntypedNull extends UntypedNode { + UntypedNull(); + + final dynamic value = null; +} diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_object.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_object.dart new file mode 100644 index 0000000..b539295 --- /dev/null +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_object.dart @@ -0,0 +1,8 @@ +part of '../../kiota_abstractions.dart'; + +/// Represents an untyped node with object value. +class UntypedObject extends UntypedNode { + UntypedObject(this.properties); + + Map properties; +} diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart new file mode 100644 index 0000000..149e037 --- /dev/null +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart @@ -0,0 +1,8 @@ +part of '../../kiota_abstractions.dart'; + +class UntypedString extends UntypedNode { + + UntypedString(this.value); + + final String value; +} diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index 0d2643b..ab5feb4 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -36,16 +36,17 @@ class JsonParseNode implements ParseNode { } @override - Iterable getCollectionOfEnumValues(EnumFactory factory) { - final result = []; + Iterable getCollectionOfEnumValues( + EnumFactory factory, + ) { + final result = []; if (_node is List) { - for (final value in _node) - { - final enumValue = factory(value.toString()); - if(enumValue != null) { - result.add(enumValue); - } + for (final value in _node) { + final enumValue = factory(value.toString()); + if (enumValue != null) { + result.add(enumValue); } + } } return result; } @@ -56,16 +57,15 @@ class JsonParseNode implements ParseNode { ) { final result = []; if (_node is List) { - for (final value in _node) - { - final node = JsonParseNode(value) + for (final value in _node) { + final node = JsonParseNode(value) ..onAfterAssignFieldValues = onAfterAssignFieldValues ..onBeforeAssignFieldValues = onBeforeAssignFieldValues; - final objectValue = node.getObjectValue(factory); - if(objectValue != null){ - result.add(objectValue); - } + final objectValue = node.getObjectValue(factory); + if (objectValue != null) { + result.add(objectValue); } + } } return result; } @@ -117,8 +117,11 @@ class JsonParseNode implements ParseNode { @override T? getObjectValue(ParsableFactory factory) { - // TODO(Kees): Handle getting untyped value final item = factory(this); + if (item is UntypedNode) { + return getUntypedValue(_node)! as T; + } + onBeforeAssignFieldValues?.call(item); _assignFieldValues(item); onAfterAssignFieldValues?.call(item); @@ -163,4 +166,68 @@ class JsonParseNode implements ParseNode { TimeOnly? getTimeOnlyValue() { return _node == null ? null : TimeOnly.fromDateTimeString(_node.toString()); } + + UntypedNode? getUntypedValue(dynamic node) { + if (node == null) { + return UntypedNull(); + } + + if (node is List) { + final arrayValue = getCollectionOfUntypedValues(node); + return UntypedArray(arrayValue); + } + + if (node is Map) { + final propertiesMap = {}; + for (final entry in node.entries) { + final fieldKey = entry.key as String; + final fieldValue = entry.value; + final childNode = JsonParseNode(fieldValue); + // childNode.setOnBeforeAssignFieldValues(this.getOnBeforeAssignFieldValues()); + // childNode.setOnAfterAssignFieldValues(this.getOnAfterAssignFieldValues()); + propertiesMap[fieldKey] = + childNode.getUntypedValue(fieldValue)!; + } + return UntypedObject(propertiesMap); + } + + final doubleValue = double.tryParse(node.toString()); + if (doubleValue != null) { + return UntypedDouble(doubleValue); + } + + final intValue = int.tryParse(node.toString()); + if (intValue != null) { + return UntypedInteger(intValue); + } + + final boolValue = bool.tryParse(node.toString()); + if (boolValue != null) { + return UntypedBoolean(value: boolValue); + } + + if (node is String) { + return UntypedString(node); + } + + throw ArgumentError.value(node, 'node'); + } + + /// Gets the collection of untyped values of the node. + Iterable getCollectionOfUntypedValues(List nodeArray) { + final result = []; + + nodeArray.forEach((arrayElement) { + final node = JsonParseNode(arrayElement) + ..onAfterAssignFieldValues = onAfterAssignFieldValues + ..onBeforeAssignFieldValues = onBeforeAssignFieldValues; + + final value = node.getUntypedValue(arrayElement); + if (value != null) { + result.add(value); + } + }); + + return result; + } } diff --git a/packages/kiota_serialization_json/test/json_parse_node_test.dart b/packages/kiota_serialization_json/test/json_parse_node_test.dart index 7441a3d..5ea5353 100644 --- a/packages/kiota_serialization_json/test/json_parse_node_test.dart +++ b/packages/kiota_serialization_json/test/json_parse_node_test.dart @@ -7,6 +7,7 @@ import 'package:test/test.dart'; import 'derived_microsoft_graph_user.dart'; import 'microsoft_graph_user.dart'; import 'test_enums.dart'; +import 'untyped_test_entity.dart'; const _testUserJson = r''' { @@ -117,7 +118,6 @@ void main() { final testEntity = jsonParseNode .getObjectValue(MicrosoftGraphUser.createFromDiscriminator); - print(testEntity); expect(testEntity, isNotNull); if (testEntity != null) { expect(testEntity.additionalData, isNotEmpty); @@ -149,5 +149,20 @@ void main() { ); } }); + + test('Get user object from untyped Json', () { + final jsonParseNode = JsonParseNode(jsonDecode(_testUntypedJson)); + final testEntity = jsonParseNode + .getObjectValue(UntypedTestEntity.createFromDiscriminator); + + expect(testEntity, isNotNull); + if (testEntity != null) { + expect(testEntity.additionalData, isNotEmpty); + + final location = testEntity.location; + expect(location, isNotNull); + expect(location is UntypedObject, isTrue); + } + }); }); } diff --git a/packages/kiota_serialization_json/test/untyped_test_entity.dart b/packages/kiota_serialization_json/test/untyped_test_entity.dart new file mode 100644 index 0000000..2b4a1f2 --- /dev/null +++ b/packages/kiota_serialization_json/test/untyped_test_entity.dart @@ -0,0 +1,51 @@ +import 'package:kiota_abstractions/kiota_abstractions.dart'; + +class UntypedTestEntity extends Parsable implements AdditionalDataHolder { + UntypedTestEntity(); + + factory UntypedTestEntity.createFromDiscriminator(ParseNode parseNode) { + final discriminatorValue = parseNode.getChildNode('@odata.type')?.getStringValue(); + return switch(discriminatorValue) + { + _ => UntypedTestEntity() + }; + } + + /// Stores additional data not described in the OpenAPI description + /// found when deserializing. + /// Can be used for serialization as well. + @override + Map additionalData = {}; + + String? id; + String? title; + UntypedNode? location; + UntypedNode? keywords; + UntypedNode? detail; + UntypedNode? table; + + @override + Map getFieldDeserializers() { + return { + 'id': (node) => id = node.getStringValue(), + 'title': (node) => title = node.getStringValue(), + 'location': (node) => location = node.getObjectValue(UntypedNode.createFromDiscriminatorValue), + 'keywords': (node) => keywords = node.getObjectValue(UntypedNode.createFromDiscriminatorValue), + 'detail': (node) => detail = node.getObjectValue(UntypedNode.createFromDiscriminatorValue), + 'table': (node) => table = node.getObjectValue(UntypedNode.createFromDiscriminatorValue), + }; + } + + @override + void serialize(SerializationWriter writer) { + writer + ..writeStringValue('id', id) + ..writeStringValue('title', title) + ..writeObjectValue('location', location) + ..writeObjectValue('keywords', keywords) + ..writeObjectValue('detail', detail) + ..writeObjectValue('table', table) + ..writeAdditionalData(additionalData); + } + +} From 69aae59f17efed96b041b3568420ae7b57053f4b Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Fri, 27 Sep 2024 15:03:06 +0200 Subject: [PATCH 25/69] Start with json serialization --- .../lib/src/json_serialization_writer.dart | 66 ++++++++++++------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index 10ff52fb..64fb328 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -2,11 +2,12 @@ part of '../kiota_serialization_json.dart'; class JsonSerializationWriter implements SerializationWriter { final StringBuffer _buffer = StringBuffer(); - bool _isFirst = true; - static UnsupportedError _noStructuredDataError() { - return UnsupportedError('Text does not support structured data'); - } + final openingObject = '{'; + final closingObject = '}'; + final openingArray = '['; + final closingArray = ']'; + final separator = ','; @override ParsableHook? onAfterObjectSerialization; @@ -19,12 +20,15 @@ class JsonSerializationWriter implements SerializationWriter { @override Uint8List getSerializedContent() { - return utf8.encode(_buffer.toString()); + var content = _buffer.toString(); + content = content.replaceAll(', }', '}'); + content = content.replaceAll(', ]', ']'); + return utf8.encode(content); } @override void writeAdditionalData(Map value) { - throw _noStructuredDataError(); + //TODO } @override @@ -43,7 +47,7 @@ class JsonSerializationWriter implements SerializationWriter { Iterable? values, EnumSerializer serializer, ) { - throw _noStructuredDataError(); + //TODO } @override @@ -51,12 +55,25 @@ class JsonSerializationWriter implements SerializationWriter { String? key, Iterable? values, ) { - throw _noStructuredDataError(); - } + if(values == null || values.isEmpty){ + return; + } + else{ + _buffer.write('$openingObject "$key" : $openingArray'); + var first = true; + for (final value in values!) + { + if(!first){ + _buffer.write(separator);} + first = false; + value.serialize(this); + } + _buffer.write(' $closingArray $closingObject '); + }} @override void writeCollectionOfPrimitiveValues(String? key, Iterable? values) { - throw _noStructuredDataError(); + //TODO } @override @@ -94,29 +111,30 @@ class JsonSerializationWriter implements SerializationWriter { T? value, [ Iterable? additionalValuesToMerge, ]) { - throw _noStructuredDataError(); + if(value == null){ + return; + } + else if(key == null){ + value.serialize(this); + } + else + { + _buffer.write('$openingObject "$key" :'); + value.serialize(this); + _buffer.write(' $closingObject$separator '); + } } @override void writeStringValue(String? key, String? value) { - // text cannot have keys, so we throw if one is provided - if (key?.isNotEmpty ?? false) { - throw _noStructuredDataError(); + if (key?.isEmpty ?? true) { + return; } - // if the value is null or empty, we don't write anything if (value?.isEmpty ?? true) { return; } - - if (!_isFirst) { - throw UnsupportedError( - 'A value was already written for this serialization writer, text content only supports a single value', - ); - } - - _isFirst = false; - _buffer.write(value); + _buffer.write('"$key" : "$value"$separator '); } @override From 94106c78cd2d1ce55a699ae9de634c27428f3c43 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 1 Oct 2024 07:13:36 +0200 Subject: [PATCH 26/69] Fix entry mssing from originalKeys --- packages/kiota_abstractions/lib/src/case_insensitive_map.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/kiota_abstractions/lib/src/case_insensitive_map.dart b/packages/kiota_abstractions/lib/src/case_insensitive_map.dart index a3795f8..f75a960 100644 --- a/packages/kiota_abstractions/lib/src/case_insensitive_map.dart +++ b/packages/kiota_abstractions/lib/src/case_insensitive_map.dart @@ -109,6 +109,7 @@ class CaseInsensitiveMap implements Map { @override V putIfAbsent(K key, V Function() ifAbsent) { + _originalKeys[normalizeKey(key)] = key; return _contents.putIfAbsent(normalizeKey(key), ifAbsent); } From 2d0cb4a3943ad0ffd9e3bb9669bc5c848be8a02a Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 1 Oct 2024 08:53:03 +0200 Subject: [PATCH 27/69] Small improvements in json serialization --- .../lib/src/json_serialization_writer.dart | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index 64fb328..3da053a 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -1,7 +1,7 @@ part of '../kiota_serialization_json.dart'; class JsonSerializationWriter implements SerializationWriter { - final StringBuffer _buffer = StringBuffer(); + final List _buffer = []; final openingObject = '{'; final closingObject = '}'; @@ -20,10 +20,7 @@ class JsonSerializationWriter implements SerializationWriter { @override Uint8List getSerializedContent() { - var content = _buffer.toString(); - content = content.replaceAll(', }', '}'); - content = content.replaceAll(', ]', ']'); - return utf8.encode(content); + return utf8.encode('{${_buffer.join()}}'); } @override @@ -59,16 +56,21 @@ class JsonSerializationWriter implements SerializationWriter { return; } else{ - _buffer.write('$openingObject "$key" : $openingArray'); + _buffer.add('"$key":$openingArray'); var first = true; - for (final value in values!) + for (final value in values) { if(!first){ - _buffer.write(separator);} + _buffer.add(separator);} first = false; + _buffer.add(openingObject); value.serialize(this); + _buffer.add(closingObject); } - _buffer.write(' $closingArray $closingObject '); + if(_buffer.last == separator){ + _buffer.removeLast(); + } + _buffer.add(closingArray); }} @override @@ -119,9 +121,12 @@ class JsonSerializationWriter implements SerializationWriter { } else { - _buffer.write('$openingObject "$key" :'); + _buffer.add('"$key":$openingObject'); value.serialize(this); - _buffer.write(' $closingObject$separator '); + if(_buffer.last == separator){ + _buffer.removeLast(); + } + _buffer.add(closingObject); } } @@ -134,7 +139,8 @@ class JsonSerializationWriter implements SerializationWriter { if (value?.isEmpty ?? true) { return; } - _buffer.write('"$key" : "$value"$separator '); + _buffer..add('"$key":"$value"') + ..add(separator); } @override From 512baf8658b32cbbddf6968a4395a6665c309dca Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 1 Oct 2024 09:57:11 +0200 Subject: [PATCH 28/69] Add to correct variable --- .../lib/src/extensions/request_information_extensions.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart index 7350f4a..befd80f 100644 --- a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart +++ b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart @@ -13,7 +13,7 @@ extension RequestInformationExtensions on RequestInformation { /// Vanity method to add headers to the request. void addHeaders(HttpHeaders headers) { - headers.addAll(headers); + this.headers.addAll(headers); } /// Vanity method to add query parameters to the request. From f40cfbf5b36d7ba29373f2a5fe2f5ab5f76f6a35 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 1 Oct 2024 11:19:47 +0200 Subject: [PATCH 29/69] more small improvements to json serialization --- .../lib/src/json_serialization_writer.dart | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index 3da053a..afb7519 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -20,7 +20,8 @@ class JsonSerializationWriter implements SerializationWriter { @override Uint8List getSerializedContent() { - return utf8.encode('{${_buffer.join()}}'); + removeSeparator(); + return utf8.encode(_buffer.join()); } @override @@ -61,16 +62,16 @@ class JsonSerializationWriter implements SerializationWriter { for (final value in values) { if(!first){ - _buffer.add(separator);} + _buffer.add(separator); + } first = false; _buffer.add(openingObject); value.serialize(this); + removeSeparator(); _buffer.add(closingObject); } - if(_buffer.last == separator){ - _buffer.removeLast(); - } - _buffer.add(closingArray); + _buffer..add(closingArray) + ..add(separator); }} @override @@ -117,16 +118,19 @@ class JsonSerializationWriter implements SerializationWriter { return; } else if(key == null){ + _buffer.add(openingObject); value.serialize(this); + removeSeparator(); + _buffer..add(closingObject) + ..add(separator); } else { _buffer.add('"$key":$openingObject'); value.serialize(this); - if(_buffer.last == separator){ - _buffer.removeLast(); - } - _buffer.add(closingObject); + removeSeparator(); + _buffer..add(closingObject) + ..add(separator); } } @@ -162,4 +166,10 @@ class JsonSerializationWriter implements SerializationWriter { void writeUuidValue(String? key, UuidValue? value) { writeStringValue(key, value?.uuid); } + + void removeSeparator(){ + if(_buffer.last == separator){ + _buffer.removeLast(); + } + } } From a2b51e25d242eb48c4e0588c71db09957a45184f Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 1 Oct 2024 14:26:36 +0200 Subject: [PATCH 30/69] Added some json serialization tests --- .../test/json_serialization_writer_test.dart | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 packages/kiota_serialization_json/test/json_serialization_writer_test.dart diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart new file mode 100644 index 0000000..162de99 --- /dev/null +++ b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart @@ -0,0 +1,36 @@ +import 'dart:convert'; + +import 'package:kiota_abstractions/kiota_abstractions.dart'; +import 'package:kiota_serialization_json/kiota_serialization_json.dart'; +import 'package:test/test.dart'; + +String? _httpMethodEnumSerializer(HttpMethod? value) => value?.name; + +void main() { + group('JsonSerializationWriter', () { + test('writeCollectionOfEnumValues', () { + final writer = JsonSerializationWriter() + ..writeCollectionOfEnumValues( + 'key', + [HttpMethod.get, HttpMethod.post, HttpMethod.patch], + _httpMethodEnumSerializer, + ); + + expect( + utf8.decode(writer.getSerializedContent()), + equals('{"key":["get","post","patch"]}'), + ); + }); + test('writeCollectionOfPrimitiveValues', () { + final writer = JsonSerializationWriter() + ..writeCollectionOfPrimitiveValues( + 'intlist', + [1,2,3],); + + expect( + utf8.decode(writer.getSerializedContent()), + equals('{"intlist":["1","2","3"]}'), + ); + }); + }); +} From 6a87d64e659a0577c7bb7f3f28bbf12a6420e759 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 1 Oct 2024 14:57:43 +0200 Subject: [PATCH 31/69] Implemented other collection methods --- .../lib/src/json_serialization_writer.dart | 65 +++++++++++++++++-- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index afb7519..852217b 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -45,8 +45,28 @@ class JsonSerializationWriter implements SerializationWriter { Iterable? values, EnumSerializer serializer, ) { - //TODO - } + if(values == null || values.isEmpty){ + return; + } + else{ + final writeAsObject = _buffer.isEmpty; + final opening = writeAsObject? openingObject : ''; + _buffer.add('$opening"$key":$openingArray'); + var first = true; + for (final value in values) + { + if(!first){ + _buffer.add(separator); + } + first = false; + _buffer.add('"${serializer(value)}"'); + } + _buffer.add(closingArray); + if(writeAsObject){ + _buffer.add(closingObject); + } + _buffer.add(separator); + }} @override void writeCollectionOfObjectValues( @@ -76,8 +96,28 @@ class JsonSerializationWriter implements SerializationWriter { @override void writeCollectionOfPrimitiveValues(String? key, Iterable? values) { - //TODO - } + if(values == null || values.isEmpty){ + return; + } + else{ + final writeAsObject = _buffer.isEmpty; + final opening = writeAsObject? openingObject : ''; + _buffer.add('$opening"$key":$openingArray'); + var first = true; + for (final value in values) + { + if(!first){ + _buffer.add(separator); + } + first = false; + _buffer.add('"${_getAnyValue(value!)}"'); + } + _buffer.add(closingArray); + if(writeAsObject){ + _buffer.add(closingObject); + } + _buffer.add(separator); + }} @override void writeDateTimeValue(String? key, DateTime? value) { @@ -172,4 +212,21 @@ class JsonSerializationWriter implements SerializationWriter { _buffer.removeLast(); } } + + String _getAnyValue(Object value) { + switch (value) { + case final String s: + return s; + case final UuidValue u: + return u.uuid; + case final DateTime d: + return d.toIso8601String(); + case final DateOnly d: + return d.toRfc3339String(); + case final TimeOnly t: + return t.toRfc3339String(); + default: + return value.toString(); + } + } } From b7cd0577b98c366cf33dfb1753c935377964b4d4 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 1 Oct 2024 15:33:44 +0200 Subject: [PATCH 32/69] Serialize additional data, added test for object serialization --- .../lib/src/json_serialization_writer.dart | 5 ++++- .../test/json_serialization_writer_test.dart | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index 852217b..d0fa95b 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -26,7 +26,10 @@ class JsonSerializationWriter implements SerializationWriter { @override void writeAdditionalData(Map value) { - //TODO + for(final entry in value.entries){ + _buffer..add('"${entry.key}":"${_getAnyValue(entry.value as Object)}"') + ..add(separator); + } } @override diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart index 162de99..6acddf2 100644 --- a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart +++ b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:kiota_abstractions/kiota_abstractions.dart'; import 'package:kiota_serialization_json/kiota_serialization_json.dart'; import 'package:test/test.dart'; +import 'microsoft_graph_user.dart'; String? _httpMethodEnumSerializer(HttpMethod? value) => value?.name; @@ -32,5 +33,24 @@ void main() { equals('{"intlist":["1","2","3"]}'), ); }); + + test('writeObject', () { + final simpleUser = MicrosoftGraphUser() + ..officeLocation='at the desk' + ..workDuration=const Duration(hours: 40) + ..birthDay=DateOnly.fromDateTime(DateTime.parse('2024-10-01 00:00:00')) + ..heightInMetres=1.7 + ..additionalData={'a':'some value', 'b': 'some other value'}; + + final writer = JsonSerializationWriter() + ..writeObjectValue( + null, simpleUser); + + expect( + utf8.decode(writer.getSerializedContent()), + equals('{"officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":"1.7","a":"some value","b":"some other value"}'), + ); + }); + }); } From 944bfc9121672337d496503650cd6a87cf8ce7a0 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 2 Oct 2024 09:13:39 +0200 Subject: [PATCH 33/69] Added some more tests for json serialization --- .../test/json_serialization_writer_test.dart | 39 ++++++++++++++-- .../test/microsoft_graph_group.dart | 46 +++++++++++++++++++ .../test/microsoft_graph_user.dart | 15 ++++-- 3 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 packages/kiota_serialization_json/test/microsoft_graph_group.dart diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart index 6acddf2..5aceba9 100644 --- a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart +++ b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart @@ -1,10 +1,13 @@ import 'dart:convert'; - import 'package:kiota_abstractions/kiota_abstractions.dart'; import 'package:kiota_serialization_json/kiota_serialization_json.dart'; import 'package:test/test.dart'; +import 'package:uuid/uuid.dart'; + +import 'microsoft_graph_group.dart'; import 'microsoft_graph_user.dart'; + String? _httpMethodEnumSerializer(HttpMethod? value) => value?.name; void main() { @@ -36,11 +39,16 @@ void main() { test('writeObject', () { final simpleUser = MicrosoftGraphUser() + ..id=UuidValue.fromString('01924bf0-a3dd-707c-bfb2-5826130b96f2') + ..createdDateTime=DateTime(2023,12,1,15,15) ..officeLocation='at the desk' ..workDuration=const Duration(hours: 40) ..birthDay=DateOnly.fromDateTime(DateTime.parse('2024-10-01 00:00:00')) ..heightInMetres=1.7 - ..additionalData={'a':'some value', 'b': 'some other value'}; + ..startWorkTime=TimeOnly.fromDateTimeString('06:00') + ..active=true + ..numbers=[2,3,5] + ..additionalData={'a':'some value', 'b': 12, 'c' : false}; final writer = JsonSerializationWriter() ..writeObjectValue( @@ -48,9 +56,34 @@ void main() { expect( utf8.decode(writer.getSerializedContent()), - equals('{"officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":"1.7","a":"some value","b":"some other value"}'), + equals('{"id":"01924bf0-a3dd-707c-bfb2-5826130b96f2","createdDateTime":"2023-12-01T15:15:00.000","officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":"1.7","startWorkTime":"06:00:00","active":"true","numbers":["2","3","5"],"a":"some value","b":"12","c":"false"}'), ); }); + test('writeSecondObject', () { + final user1 = MicrosoftGraphUser() + ..officeLocation='on a chair' + ..workDuration=const Duration(hours: 2) + ..additionalData={'a':'#1 coworker'}; + final user2 = MicrosoftGraphUser() + ..workDuration=const Duration(hours: 12) + ..active=true; + final user3 = MicrosoftGraphUser() + ..heightInMetres=1.9 + ..endWorkTime=TimeOnly.fromDateTimeString('17:00'); + final group = MicrosoftGraphGroup() + ..name='a group' + ..leader=user3 + ..members=[user1,user2]; + + final writer = JsonSerializationWriter() + ..writeObjectValue( + null, group,); + + expect( + utf8.decode(writer.getSerializedContent()), + equals('{"name":"a group","leader":{"heightInMetres":"1.9","endWorkTime":"17:00:00"},"members":[{"officeLocation":"on a chair","workDuration":"2:00:00.000000","a":"#1 coworker"},{"workDuration":"12:00:00.000000","active":"true"}]}'), + ); + }); }); } diff --git a/packages/kiota_serialization_json/test/microsoft_graph_group.dart b/packages/kiota_serialization_json/test/microsoft_graph_group.dart new file mode 100644 index 0000000..f5876a2 --- /dev/null +++ b/packages/kiota_serialization_json/test/microsoft_graph_group.dart @@ -0,0 +1,46 @@ +import 'package:kiota_abstractions/kiota_abstractions.dart'; +import 'microsoft_graph_user.dart'; + +class MicrosoftGraphGroup extends Parsable implements AdditionalDataHolder { + MicrosoftGraphGroup(); + + @override + Map additionalData = {}; + + String? id; + String? name; + MicrosoftGraphUser? leader; + Iterable members = []; + + @override + void serialize(SerializationWriter writer) { + writer + ..writeStringValue('id', id) + ..writeStringValue('name', name) + ..writeObjectValue('leader', leader) + ..writeCollectionOfObjectValues('members', members) + ..writeAdditionalData(additionalData); + } + + @override + Map getFieldDeserializers() { + return { + 'id': (node) => id = node.getStringValue(), + 'name': (node) => + name = node.getStringValue(), + 'leader': (node) => leader = node.getObjectValue(MicrosoftGraphUser.createFromDiscriminator), + 'members': (node) => members = node.getCollectionOfObjectValues(MicrosoftGraphUser.createFromDiscriminator), + }; + } + + @override + String toString() { + return ''' + id: $id + name: $name + leader: $leader + members: $members + additionalData: $additionalData + '''; + } +} diff --git a/packages/kiota_serialization_json/test/microsoft_graph_user.dart b/packages/kiota_serialization_json/test/microsoft_graph_user.dart index dd2d318..efddf9f 100644 --- a/packages/kiota_serialization_json/test/microsoft_graph_user.dart +++ b/packages/kiota_serialization_json/test/microsoft_graph_user.dart @@ -1,4 +1,5 @@ import 'package:kiota_abstractions/kiota_abstractions.dart'; +import 'package:uuid/uuid.dart'; import 'derived_microsoft_graph_user.dart'; import 'test_enums.dart'; @@ -26,7 +27,7 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { @override Map additionalData = {}; - String? id; + UuidValue? id; NamingEnum? namingEnum; DateOnly? birthDay; TimeOnly? startWorkTime; @@ -35,11 +36,13 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { DateTime? createdDateTime; double? heightInMetres; String? officeLocation; + bool? active; + Iterable numbers=[]; @override void serialize(SerializationWriter writer) { writer - ..writeStringValue('id', id) + ..writeUuidValue('id', id) ..writeEnumValue( 'namingEnum', namingEnum, _namingEnumSerializer) ..writeDateTimeValue('createdDateTime', createdDateTime) @@ -49,13 +52,15 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { ..writeDoubleValue('heightInMetres', heightInMetres) ..writeTimeOnlyValue('startWorkTime', startWorkTime) ..writeTimeOnlyValue('endWorkTime', endWorkTime) + ..writeBoolValue('active', value:active) + ..writeCollectionOfPrimitiveValues('numbers', numbers) ..writeAdditionalData(additionalData); } @override Map getFieldDeserializers() { return { - 'id': (node) => id = node.getStringValue(), + 'id': (node) => id = node.getGuidValue(), 'namingEnum': (node) => namingEnum = node.getEnumValue(_namingEnumFactory), 'createdDateTime': (node) => createdDateTime = node.getDateTimeValue(), @@ -65,6 +70,8 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { 'birthDay': (node) => birthDay = node.getDateOnlyValue(), 'startWorkTime': (node) => startWorkTime = node.getTimeOnlyValue(), 'endWorkTime': (node) => endWorkTime = node.getTimeOnlyValue(), + 'active': (node) => active = node.getBoolValue(), + 'numbers' : (node) => numbers = node.getCollectionOfPrimitiveValues(), }; } @@ -80,6 +87,8 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { birthDay: ${birthDay?.year}-${birthDay?.month}-${birthDay?.day} startWorkTime: ${startWorkTime?.hours}:${startWorkTime?.minutes} endWorkTime: ${endWorkTime?.hours}:${endWorkTime?.minutes} + active: $active + numbers: $numbers additionalData: $additionalData '''; } From 9f417eaac81839e8e0f0c78d348c500e8f9ea4d6 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 2 Oct 2024 10:32:58 +0200 Subject: [PATCH 34/69] Some small improvements and added test for enum deserialization --- .../lib/src/serialization/untyped_node.dart | 12 ++++++------ .../lib/src/http_client_request_adapter.dart | 6 +++--- .../test/json_parse_node_test.dart | 13 ++++++++++++- .../test/microsoft_graph_user.dart | 2 +- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart index 516dd09..0fee423 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart @@ -2,7 +2,13 @@ part of '../../kiota_abstractions.dart'; /// Base class for untyped node. class UntypedNode implements Parsable { + UntypedNode(); + /// Creates a new [UntypedNode] instance of the appropriate class + /// based on discriminator value. + factory UntypedNode.createFromDiscriminatorValue(ParseNode parseNode) { + return UntypedNode(); + } /// The deserialization information for the current model. /// Returns a map of serializer methods for this object. @override @@ -20,10 +26,4 @@ class UntypedNode implements Parsable { Object getValue() { throw Exception('getValue is implemented for derived types of UntypedNode'); } - - /// Creates a new [UntypedNode] instance of the appropriate class - /// based on discriminator value. - static UntypedNode createFromDiscriminatorValue(ParseNode parseNode) { - return UntypedNode(); - } } diff --git a/packages/kiota_http/lib/src/http_client_request_adapter.dart b/packages/kiota_http/lib/src/http_client_request_adapter.dart index ac529ab..902c4d8 100644 --- a/packages/kiota_http/lib/src/http_client_request_adapter.dart +++ b/packages/kiota_http/lib/src/http_client_request_adapter.dart @@ -130,10 +130,10 @@ class HttpClientRequestAdapter implements RequestAdapter { final rootNode = await _getRootParseNode(response); final result = rootNode?.getObjectValue(errorFactory); - if (result case Exception exception) { + if (result case final Exception exception) { if (exception case final ApiException apiException) { - apiException.statusCode = statusCodeInt; - apiException.responseHeaders = headers; + apiException..statusCode = statusCodeInt + ..responseHeaders = headers; } throw exception; diff --git a/packages/kiota_serialization_json/test/json_parse_node_test.dart b/packages/kiota_serialization_json/test/json_parse_node_test.dart index 5ea5353..714f236 100644 --- a/packages/kiota_serialization_json/test/json_parse_node_test.dart +++ b/packages/kiota_serialization_json/test/json_parse_node_test.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:kiota_abstractions/kiota_abstractions.dart'; import 'package:kiota_serialization_json/kiota_serialization_json.dart'; import 'package:test/test.dart'; +import 'package:uuid/uuid.dart'; import 'derived_microsoft_graph_user.dart'; import 'microsoft_graph_user.dart'; @@ -125,7 +126,7 @@ void main() { expect(testEntity.additionalData['jobTitle'], 'Auditor'); expect(testEntity.officeLocation, null); - expect(testEntity.id, '48d31887-5fad-4d73-a9f5-3c356e68a038'); + expect(testEntity.id, UuidValue.fromString('48d31887-5fad-4d73-a9f5-3c356e68a038')); expect(testEntity.namingEnum, NamingEnum.item2SubItem1); expect(testEntity.workDuration, const Duration(hours: 1)); expect(testEntity.startWorkTime, TimeOnly.fromComponents(8, 0)); @@ -164,5 +165,15 @@ void main() { expect(location is UntypedObject, isTrue); } }); + test('Get enumcollection from json', () { + final jsonParseNode = JsonParseNode(jsonDecode(_testCollectionOfEnumsJson)); + final testCollection = jsonParseNode + .getCollectionOfEnumValues((value)=> NamingEnum.values.where((ne) => ne.value == value).firstOrNull); + + expect(testCollection, isNotNull); + expect(testCollection.length, 2); + expect(testCollection.first, NamingEnum.item2SubItem1); + expect(testCollection.last, NamingEnum.item3SubItem1); + }); }); } diff --git a/packages/kiota_serialization_json/test/microsoft_graph_user.dart b/packages/kiota_serialization_json/test/microsoft_graph_user.dart index efddf9f..f8eb075 100644 --- a/packages/kiota_serialization_json/test/microsoft_graph_user.dart +++ b/packages/kiota_serialization_json/test/microsoft_graph_user.dart @@ -44,7 +44,7 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { writer ..writeUuidValue('id', id) ..writeEnumValue( - 'namingEnum', namingEnum, _namingEnumSerializer) + 'namingEnum', namingEnum, _namingEnumSerializer,) ..writeDateTimeValue('createdDateTime', createdDateTime) ..writeStringValue('officeLocation', officeLocation) ..writeDurationValue('workDuration', workDuration) From 3a6b176d2ab729cb73061564624ed5dae0f2af20 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 2 Oct 2024 10:59:41 +0200 Subject: [PATCH 35/69] added calls to onBefore/Start/AfterObjectSerialization --- .../lib/src/json_serialization_writer.dart | 14 ++++++++++---- .../test/json_serialization_writer_test.dart | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index d0fa95b..dc28550 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -161,19 +161,25 @@ class JsonSerializationWriter implements SerializationWriter { return; } else if(key == null){ + onBeforeObjectSerialization?.call(value); _buffer.add(openingObject); + onStartObjectSerialization?.call(value, this); value.serialize(this); removeSeparator(); - _buffer..add(closingObject) - ..add(separator); + _buffer.add(closingObject); + onAfterObjectSerialization?.call(value); + _buffer.add(separator); } else { + onBeforeObjectSerialization?.call(value); _buffer.add('"$key":$openingObject'); + onStartObjectSerialization?.call(value, this); value.serialize(this); removeSeparator(); - _buffer..add(closingObject) - ..add(separator); + _buffer.add(closingObject); + onAfterObjectSerialization?.call(value); + _buffer.add(separator); } } diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart index 5aceba9..9a976fa 100644 --- a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart +++ b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart @@ -52,7 +52,7 @@ void main() { final writer = JsonSerializationWriter() ..writeObjectValue( - null, simpleUser); + null, simpleUser,); expect( utf8.decode(writer.getSerializedContent()), From 688567c2fc2d07a7360d71bb5e4188ba144a2403 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 2 Oct 2024 12:01:50 +0200 Subject: [PATCH 36/69] Fix readme mistakes --- packages/kiota_serialization_json/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kiota_serialization_json/README.md b/packages/kiota_serialization_json/README.md index a46affc..d1087c4 100644 --- a/packages/kiota_serialization_json/README.md +++ b/packages/kiota_serialization_json/README.md @@ -1,4 +1,4 @@ -The `kiota_serialization_json` package is the Dart Text serialization library implementation to +The `kiota_serialization_json` package is the Dart Json serialization library implementation to handle `application/json` responses. ## Usage @@ -9,7 +9,7 @@ Install the package in the generated project: > > ```yaml > dependencies: -> kiota_serialization_text: +> kiota_serialization_json: > git: > url: https://github.com/ricardoboss/dart_kiota.git > ref: main From 061636cd8fd55db7a1773a098b9e93a4028288d9 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 8 Oct 2024 13:32:57 +0200 Subject: [PATCH 37/69] Added testcases for issues found --- .../test/case_insensitive_map_test.dart | 20 +++++++++++++++++++ .../test/request_information_test.dart | 12 +++++++++++ 2 files changed, 32 insertions(+) create mode 100644 packages/kiota_abstractions/test/case_insensitive_map_test.dart diff --git a/packages/kiota_abstractions/test/case_insensitive_map_test.dart b/packages/kiota_abstractions/test/case_insensitive_map_test.dart new file mode 100644 index 0000000..6164f62 --- /dev/null +++ b/packages/kiota_abstractions/test/case_insensitive_map_test.dart @@ -0,0 +1,20 @@ +// ignore_for_file: avoid_redundant_argument_values + +import 'package:kiota_abstractions/kiota_abstractions.dart'; +import 'package:test/test.dart'; + +void main() { + group('CaseInsensitiveMap', () { + test('putIfAbsent', () { + final headers = HttpHeaders() + ..putIfAbsent('key', () => {'value'}) + ..map((name, values) { + return MapEntry(name, values.join(', ')); + }); + expect( + headers['key'], + {'value'}, + ); + }); + }); +} diff --git a/packages/kiota_abstractions/test/request_information_test.dart b/packages/kiota_abstractions/test/request_information_test.dart index fd7a2ff..b15e00c 100644 --- a/packages/kiota_abstractions/test/request_information_test.dart +++ b/packages/kiota_abstractions/test/request_information_test.dart @@ -226,5 +226,17 @@ void main() { // Assert expect(testRequest.uri.toString(), 'http://localhost/first,second'); }); + + test('Add headers', () { + // Arrange + final testRequest = RequestInformation(); + final headers = HttpHeaders()..putIfAbsent('key', () => {'value'}); + + // Act + testRequest.addHeaders(headers); + + // Assert + expect(testRequest.headers['key'], {'value'}); + }); }); } From ac2c00bdae2207befe6d57c1976a5db72b93c055 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 9 Oct 2024 07:48:28 +0200 Subject: [PATCH 38/69] don't use late --- .../src/extensions/request_information_extensions.dart | 9 ++++----- .../lib/src/request_configuration.dart | 4 +++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart index befd80f..a78baea 100644 --- a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart +++ b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart @@ -137,15 +137,14 @@ extension RequestInformationExtensions on RequestInformation { content = writer.getSerializedContent(); } - void configure(void Function(RequestConfiguration)? configurator, T Function() createParameters) { - if (configurator == null) { + void configure(void Function(RequestConfiguration)? configurator, T Function()? createParameters) { + if (configurator == null || createParameters == null) { return; } - final config = RequestConfiguration() - ..queryParameters = createParameters(); + final config = RequestConfiguration(queryParameters: createParameters()); configurator(config); - + addQueryParameters(config.queryParameters.getQueryParameters()); addHeaders(config.headers); addRequestOptions(config.options); diff --git a/packages/kiota_abstractions/lib/src/request_configuration.dart b/packages/kiota_abstractions/lib/src/request_configuration.dart index 4a448d9..82d9788 100644 --- a/packages/kiota_abstractions/lib/src/request_configuration.dart +++ b/packages/kiota_abstractions/lib/src/request_configuration.dart @@ -2,11 +2,13 @@ part of '../kiota_abstractions.dart'; /// Request configuration type for [BaseRequestBuilder]s. class RequestConfiguration { + + RequestConfiguration({required this.queryParameters}); /// The HTTP headers of the request. HttpHeaders headers = HttpHeaders(); /// The request options. List options = []; - late T queryParameters; + T queryParameters; } From c31b5e7cf3455002a1d785c87d93c7a5d6ecf53f Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 9 Oct 2024 14:43:18 +0200 Subject: [PATCH 39/69] Revert "Don't create copy of ApiException to throw, because then all values in subclasses of ApiException get lost" This reverts commit 79122e090c49e2957b64ccf70eb6eacfe0e7a5a2. --- packages/kiota_abstractions/lib/src/api_exception.dart | 4 ++-- .../lib/src/http_client_request_adapter.dart | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/api_exception.dart b/packages/kiota_abstractions/lib/src/api_exception.dart index 21d1903..876a966 100644 --- a/packages/kiota_abstractions/lib/src/api_exception.dart +++ b/packages/kiota_abstractions/lib/src/api_exception.dart @@ -12,13 +12,13 @@ class ApiException implements Exception { }); /// The HTTP status code of the response. - int? statusCode; + final int? statusCode; /// An optional message that describes the error. final String? message; /// The headers of the response. - Map>? responseHeaders; + final Map>? responseHeaders; /// The inner exceptions that caused this exception. final Iterable? innerExceptions; diff --git a/packages/kiota_http/lib/src/http_client_request_adapter.dart b/packages/kiota_http/lib/src/http_client_request_adapter.dart index 902c4d8..c30378b 100644 --- a/packages/kiota_http/lib/src/http_client_request_adapter.dart +++ b/packages/kiota_http/lib/src/http_client_request_adapter.dart @@ -130,10 +130,12 @@ class HttpClientRequestAdapter implements RequestAdapter { final rootNode = await _getRootParseNode(response); final result = rootNode?.getObjectValue(errorFactory); - if (result case final Exception exception) { - if (exception case final ApiException apiException) { - apiException..statusCode = statusCodeInt - ..responseHeaders = headers; + if (result case Exception exception) { + if (exception case final ApiException apiException) { + exception = apiException.copyWith( + statusCode: statusCodeInt, + responseHeaders: headers, + ); } throw exception; From f1fe240f86c63ce497f1f7634ef5e7020288197c Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 9 Oct 2024 15:04:01 +0200 Subject: [PATCH 40/69] Remove generated file --- .gitignore | 5 +---- packages/kiota_http/lib/gen/version.dart | 2 -- packages/kiota_serialization_json/pubspec.yaml | 3 --- 3 files changed, 1 insertion(+), 9 deletions(-) delete mode 100644 packages/kiota_http/lib/gen/version.dart diff --git a/.gitignore b/.gitignore index 9312c58..7e89509 100644 --- a/.gitignore +++ b/.gitignore @@ -29,11 +29,8 @@ pubspec.lock build/ # ignore generated files -**/gen/** +gen/ *.mocks.dart -# Do not ignore generated version -!**/gen/version.dart - # Licenses for packages are not checked in; they are copied from the root packages/*/LICENSE diff --git a/packages/kiota_http/lib/gen/version.dart b/packages/kiota_http/lib/gen/version.dart deleted file mode 100644 index 1aa2f1b..0000000 --- a/packages/kiota_http/lib/gen/version.dart +++ /dev/null @@ -1,2 +0,0 @@ -// Generated code. Do not modify. -const packageVersion = '0.0.1-pre.1'; diff --git a/packages/kiota_serialization_json/pubspec.yaml b/packages/kiota_serialization_json/pubspec.yaml index beba452..b8a2779 100644 --- a/packages/kiota_serialization_json/pubspec.yaml +++ b/packages/kiota_serialization_json/pubspec.yaml @@ -17,6 +17,3 @@ dependencies: dev_dependencies: strict: ^2.0.0 test: ^1.25.2 - - - From 1b10f40b323225222294f301d5716c0f081d2b7e Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Thu, 10 Oct 2024 08:58:04 +0200 Subject: [PATCH 41/69] Return node directly for simple types --- .../kiota_serialization_json/lib/src/json_parse_node.dart | 6 +++--- .../kiota_serialization_json/test/json_parse_node_test.dart | 1 + .../kiota_serialization_json/test/microsoft_graph_user.dart | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index ab5feb4..4f9af73 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -13,7 +13,7 @@ class JsonParseNode implements ParseNode { @override bool? getBoolValue() { - return _node == null ? null : bool.tryParse(_node.toString()); + return _node as bool; } @override @@ -92,7 +92,7 @@ class JsonParseNode implements ParseNode { @override double? getDoubleValue() { - return _node == null ? null : double.tryParse(_node.toString()); + return _node as double; } @override @@ -112,7 +112,7 @@ class JsonParseNode implements ParseNode { @override int? getIntValue() { - return _node == null ? null : int.tryParse(_node.toString()); + return _node as int; } @override diff --git a/packages/kiota_serialization_json/test/json_parse_node_test.dart b/packages/kiota_serialization_json/test/json_parse_node_test.dart index 714f236..7f78c77 100644 --- a/packages/kiota_serialization_json/test/json_parse_node_test.dart +++ b/packages/kiota_serialization_json/test/json_parse_node_test.dart @@ -133,6 +133,7 @@ void main() { expect(testEntity.endWorkTime, TimeOnly.fromComponents(17, 0)); expect(testEntity.createdDateTime, DateTime.utc(2017, 7, 29, 3, 7, 25)); expect(testEntity.birthDay, DateOnly.fromComponents(1999, 8, 7)); + expect(testEntity.accountEnabled, true); } }); diff --git a/packages/kiota_serialization_json/test/microsoft_graph_user.dart b/packages/kiota_serialization_json/test/microsoft_graph_user.dart index f8eb075..51b365d 100644 --- a/packages/kiota_serialization_json/test/microsoft_graph_user.dart +++ b/packages/kiota_serialization_json/test/microsoft_graph_user.dart @@ -37,6 +37,7 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { double? heightInMetres; String? officeLocation; bool? active; + bool? accountEnabled; Iterable numbers=[]; @override @@ -53,6 +54,7 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { ..writeTimeOnlyValue('startWorkTime', startWorkTime) ..writeTimeOnlyValue('endWorkTime', endWorkTime) ..writeBoolValue('active', value:active) + ..writeBoolValue('accountEnabled', value:accountEnabled) ..writeCollectionOfPrimitiveValues('numbers', numbers) ..writeAdditionalData(additionalData); } @@ -71,6 +73,7 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { 'startWorkTime': (node) => startWorkTime = node.getTimeOnlyValue(), 'endWorkTime': (node) => endWorkTime = node.getTimeOnlyValue(), 'active': (node) => active = node.getBoolValue(), + 'accountEnabled': (node) => accountEnabled = node.getBoolValue(), 'numbers' : (node) => numbers = node.getCollectionOfPrimitiveValues(), }; } @@ -88,6 +91,7 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { startWorkTime: ${startWorkTime?.hours}:${startWorkTime?.minutes} endWorkTime: ${endWorkTime?.hours}:${endWorkTime?.minutes} active: $active + accountEnabled: $accountEnabled numbers: $numbers additionalData: $additionalData '''; From c11fc405f73b1b0aa4651aef6e4580311835e02f Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Thu, 10 Oct 2024 11:52:35 +0200 Subject: [PATCH 42/69] Make constructor const --- .../src/extensions/request_information_extensions.dart | 2 +- .../kiota_abstractions/lib/src/request_configuration.dart | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart index a78baea..cbf030d 100644 --- a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart +++ b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart @@ -142,7 +142,7 @@ extension RequestInformationExtensions on RequestInformation { return; } - final config = RequestConfiguration(queryParameters: createParameters()); + final config = RequestConfiguration(HttpHeaders(), [], queryParameters: createParameters()); configurator(config); addQueryParameters(config.queryParameters.getQueryParameters()); diff --git a/packages/kiota_abstractions/lib/src/request_configuration.dart b/packages/kiota_abstractions/lib/src/request_configuration.dart index 82d9788..a6eb729 100644 --- a/packages/kiota_abstractions/lib/src/request_configuration.dart +++ b/packages/kiota_abstractions/lib/src/request_configuration.dart @@ -3,12 +3,12 @@ part of '../kiota_abstractions.dart'; /// Request configuration type for [BaseRequestBuilder]s. class RequestConfiguration { - RequestConfiguration({required this.queryParameters}); + const RequestConfiguration(this.headers, this.options, {required this.queryParameters}); /// The HTTP headers of the request. - HttpHeaders headers = HttpHeaders(); + final HttpHeaders headers; /// The request options. - List options = []; + final List options; - T queryParameters; + final T queryParameters; } From 7a525f62ea4f32e40526f2184e488b239f30dbdf Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Thu, 10 Oct 2024 11:58:41 +0200 Subject: [PATCH 43/69] don't need named argument --- .../lib/src/extensions/request_information_extensions.dart | 2 +- packages/kiota_abstractions/lib/src/request_configuration.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart index cbf030d..df6f545 100644 --- a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart +++ b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart @@ -142,7 +142,7 @@ extension RequestInformationExtensions on RequestInformation { return; } - final config = RequestConfiguration(HttpHeaders(), [], queryParameters: createParameters()); + final config = RequestConfiguration(HttpHeaders(), [], createParameters()); configurator(config); addQueryParameters(config.queryParameters.getQueryParameters()); diff --git a/packages/kiota_abstractions/lib/src/request_configuration.dart b/packages/kiota_abstractions/lib/src/request_configuration.dart index a6eb729..6d9f2fc 100644 --- a/packages/kiota_abstractions/lib/src/request_configuration.dart +++ b/packages/kiota_abstractions/lib/src/request_configuration.dart @@ -3,7 +3,7 @@ part of '../kiota_abstractions.dart'; /// Request configuration type for [BaseRequestBuilder]s. class RequestConfiguration { - const RequestConfiguration(this.headers, this.options, {required this.queryParameters}); + const RequestConfiguration(this.headers, this.options, this.queryParameters); /// The HTTP headers of the request. final HttpHeaders headers; From 08a7d7d3c4d9415bd7e8428c787685e33a84e407 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Thu, 10 Oct 2024 13:26:20 +0200 Subject: [PATCH 44/69] Don't write everything as string --- .../lib/src/json_serialization_writer.dart | 38 ++++++++++++++++--- .../test/json_parse_node_test.dart | 11 ++++++ .../test/json_serialization_writer_test.dart | 6 +-- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index dc28550..39a7043 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -27,14 +27,21 @@ class JsonSerializationWriter implements SerializationWriter { @override void writeAdditionalData(Map value) { for(final entry in value.entries){ - _buffer..add('"${entry.key}":"${_getAnyValue(entry.value as Object)}"') - ..add(separator); + if(entry.value is bool || entry.value is int || entry.value is double) + { + _buffer.add('"${entry.key}":${entry.value}'); + } + else + { + _buffer.add('"${entry.key}":"${_getAnyValue(entry.value as Object)}"'); + } + _buffer.add(separator); } } @override void writeBoolValue(String? key, {bool? value}) { - writeStringValue(key, value?.toString()); + writeUnquotedValue(key, value); } @override @@ -113,7 +120,14 @@ class JsonSerializationWriter implements SerializationWriter { _buffer.add(separator); } first = false; - _buffer.add('"${_getAnyValue(value!)}"'); + if(value is bool || value is int || value is double) + { + _buffer.add('$value'); + } + else + { + _buffer.add('"${_getAnyValue(value!)}"'); + } } _buffer.add(closingArray); if(writeAsObject){ @@ -129,7 +143,7 @@ class JsonSerializationWriter implements SerializationWriter { @override void writeDoubleValue(String? key, double? value) { - writeStringValue(key, value?.toString()); + writeUnquotedValue(key, value); } @override @@ -143,7 +157,7 @@ class JsonSerializationWriter implements SerializationWriter { @override void writeIntValue(String? key, int? value) { - writeStringValue(key, value?.toString()); + writeUnquotedValue(key, value); } @override @@ -196,6 +210,18 @@ class JsonSerializationWriter implements SerializationWriter { ..add(separator); } + void writeUnquotedValue(String? key, Object? value) { + if (key?.isEmpty ?? true) { + return; + } + // if the value is null or empty, we don't write anything + if (value == null) { + return; + } + _buffer..add('"$key":$value') + ..add(separator); + } + @override void writeDateOnlyValue(String? key, DateOnly? value) { writeStringValue(key, value?.toRfc3339String()); diff --git a/packages/kiota_serialization_json/test/json_parse_node_test.dart b/packages/kiota_serialization_json/test/json_parse_node_test.dart index 7f78c77..2a4485b 100644 --- a/packages/kiota_serialization_json/test/json_parse_node_test.dart +++ b/packages/kiota_serialization_json/test/json_parse_node_test.dart @@ -176,5 +176,16 @@ void main() { expect(testCollection.first, NamingEnum.item2SubItem1); expect(testCollection.last, NamingEnum.item3SubItem1); }); + + test('Get collection of primitive values from json', () { + final jsonParseNode = JsonParseNode(jsonDecode('[2,3,5]')); + final testCollection = jsonParseNode + .getCollectionOfPrimitiveValues(); + + expect(testCollection, isNotNull); + expect(testCollection.length, 3); + expect(testCollection.first,2); + expect(testCollection.last, 5); + }); }); } diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart index 9a976fa..e2121cc 100644 --- a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart +++ b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart @@ -33,7 +33,7 @@ void main() { expect( utf8.decode(writer.getSerializedContent()), - equals('{"intlist":["1","2","3"]}'), + equals('{"intlist":[1,2,3]}'), ); }); @@ -56,7 +56,7 @@ void main() { expect( utf8.decode(writer.getSerializedContent()), - equals('{"id":"01924bf0-a3dd-707c-bfb2-5826130b96f2","createdDateTime":"2023-12-01T15:15:00.000","officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":"1.7","startWorkTime":"06:00:00","active":"true","numbers":["2","3","5"],"a":"some value","b":"12","c":"false"}'), + equals('{"id":"01924bf0-a3dd-707c-bfb2-5826130b96f2","createdDateTime":"2023-12-01T15:15:00.000","officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":1.7,"startWorkTime":"06:00:00","active":true,"numbers":[2,3,5],"a":"some value","b":12,"c":false}'), ); }); @@ -82,7 +82,7 @@ void main() { expect( utf8.decode(writer.getSerializedContent()), - equals('{"name":"a group","leader":{"heightInMetres":"1.9","endWorkTime":"17:00:00"},"members":[{"officeLocation":"on a chair","workDuration":"2:00:00.000000","a":"#1 coworker"},{"workDuration":"12:00:00.000000","active":"true"}]}'), + equals('{"name":"a group","leader":{"heightInMetres":1.9,"endWorkTime":"17:00:00"},"members":[{"officeLocation":"on a chair","workDuration":"2:00:00.000000","a":"#1 coworker"},{"workDuration":"12:00:00.000000","active":true}]}'), ); }); }); From 56b6046b86e3bcce909744657ac9313d9813fd33 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Thu, 10 Oct 2024 13:29:51 +0200 Subject: [PATCH 45/69] cast node directly Co-authored-by: Ricardo Boss --- packages/kiota_serialization_json/lib/src/json_parse_node.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index 4f9af73..055aa5f 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -74,7 +74,7 @@ class JsonParseNode implements ParseNode { Iterable getCollectionOfPrimitiveValues() { final result = []; if (_node is List) { - _node.forEach((value) => result.add(value as T)); + return _node.cast(); } return result; From 5e3d01683b8971cd72c5c87c078048482abf8db4 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Thu, 10 Oct 2024 13:56:10 +0200 Subject: [PATCH 46/69] Added suggested changes to parsenode --- .../lib/src/json_parse_node.dart | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index 055aa5f..1cdfef9 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -130,30 +130,32 @@ class JsonParseNode implements ParseNode { } void _assignFieldValues(T item) { - if (_node is Map) { - onBeforeAssignFieldValues?.call(item); - - final itemAdditionalData = item is AdditionalDataHolder - ? (item as AdditionalDataHolder).additionalData - : null; - - final fieldDeserializers = item.getFieldDeserializers(); - - for (final entry in _node.entries) { - if (fieldDeserializers.containsKey(entry.key)) { - final fieldDeserializer = fieldDeserializers[entry.key]; - if (fieldDeserializer != null) { - final itemNode = JsonParseNode(entry.value) - ..onBeforeAssignFieldValues = onBeforeAssignFieldValues - ..onAfterAssignFieldValues = onAfterAssignFieldValues; - fieldDeserializer.call(itemNode); - } - } else { - itemAdditionalData?[entry.key as String] = entry.value; + if (_node is! Map){ + return; + } + + onBeforeAssignFieldValues?.call(item); + + final itemAdditionalData = item is AdditionalDataHolder + ? (item as AdditionalDataHolder).additionalData + : null; + + final fieldDeserializers = item.getFieldDeserializers(); + + for (final entry in _node.entries) { + if (fieldDeserializers.containsKey(entry.key)) { + final fieldDeserializer = fieldDeserializers[entry.key]; + if (fieldDeserializer != null) { + final itemNode = JsonParseNode(entry.value) + ..onBeforeAssignFieldValues = onBeforeAssignFieldValues + ..onAfterAssignFieldValues = onAfterAssignFieldValues; + fieldDeserializer.call(itemNode); } + } else { + itemAdditionalData?[entry.key as String] = entry.value; } - onAfterAssignFieldValues?.call(item); } + onAfterAssignFieldValues?.call(item); } @override @@ -182,9 +184,9 @@ class JsonParseNode implements ParseNode { for (final entry in node.entries) { final fieldKey = entry.key as String; final fieldValue = entry.value; - final childNode = JsonParseNode(fieldValue); - // childNode.setOnBeforeAssignFieldValues(this.getOnBeforeAssignFieldValues()); - // childNode.setOnAfterAssignFieldValues(this.getOnAfterAssignFieldValues()); + final childNode = JsonParseNode(fieldValue) + ..onBeforeAssignFieldValues = onBeforeAssignFieldValues + ..onAfterAssignFieldValues = onAfterAssignFieldValues; propertiesMap[fieldKey] = childNode.getUntypedValue(fieldValue)!; } @@ -210,7 +212,7 @@ class JsonParseNode implements ParseNode { return UntypedString(node); } - throw ArgumentError.value(node, 'node'); + throw ArgumentError.value(node, 'node', 'Unable to parse untyped node'); } /// Gets the collection of untyped values of the node. From 29d62c7cbfeeb6ce37280b4d5a1f5303d262b50e Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 16 Oct 2024 08:25:42 +0200 Subject: [PATCH 47/69] Added test for intersection types with some small fixes --- .../lib/src/json_parse_node.dart | 3 +- .../lib/src/json_serialization_writer.dart | 20 ++- .../test/intersection_type_mock.dart | 61 +++++++++ .../test/intersection_type_test.dart | 129 ++++++++++++++++++ .../test/json_parse_node_test.dart | 5 +- .../test/json_serialization_writer_test.dart | 5 +- .../test/microsoft_graph_user.dart | 7 +- .../test/second_test_entity.dart | 34 +++++ 8 files changed, 246 insertions(+), 18 deletions(-) create mode 100644 packages/kiota_serialization_json/test/intersection_type_mock.dart create mode 100644 packages/kiota_serialization_json/test/intersection_type_test.dart create mode 100644 packages/kiota_serialization_json/test/second_test_entity.dart diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index 1cdfef9..f30c9ed 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -160,8 +160,7 @@ class JsonParseNode implements ParseNode { @override String? getStringValue() { - final result = _node.toString(); - return result == 'null' ? null : result; + return _node is String ? _node : null; } @override diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index 39a7043..2b7eeb5 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -87,7 +87,12 @@ class JsonSerializationWriter implements SerializationWriter { return; } else{ - _buffer.add('"$key":$openingArray'); + if(key?.isEmpty?? true){ + _buffer.add(openingArray); + } + else{ + _buffer.add('"$key":$openingArray'); + } var first = true; for (final value in values) { @@ -199,15 +204,18 @@ class JsonSerializationWriter implements SerializationWriter { @override void writeStringValue(String? key, String? value) { - if (key?.isEmpty ?? true) { - return; - } // if the value is null or empty, we don't write anything if (value?.isEmpty ?? true) { return; } - _buffer..add('"$key":"$value"') - ..add(separator); + if(key?.isEmpty ?? true){ + _buffer..add('"$value"') + ..add(separator); + } + else{ + _buffer..add('"$key":"$value"') + ..add(separator); + } } void writeUnquotedValue(String? key, Object? value) { diff --git a/packages/kiota_serialization_json/test/intersection_type_mock.dart b/packages/kiota_serialization_json/test/intersection_type_mock.dart new file mode 100644 index 0000000..991ee8d --- /dev/null +++ b/packages/kiota_serialization_json/test/intersection_type_mock.dart @@ -0,0 +1,61 @@ +import 'package:kiota_abstractions/kiota_abstractions.dart'; + +import './microsoft_graph_user.dart'; +import './second_test_entity.dart'; + +class IntersectionTypeMock extends Parsable implements AdditionalDataHolder { + IntersectionTypeMock(); + + factory IntersectionTypeMock.createFromDiscriminatorValue( + ParseNode parseNode,) { + final result = IntersectionTypeMock(); + if (parseNode.getStringValue() != null) { + result.stringValue = parseNode.getStringValue(); + } else if (parseNode + .getCollectionOfObjectValues( + MicrosoftGraphUser.createFromDiscriminator,) + .isNotEmpty) { + result.composedType3 = + parseNode.getCollectionOfObjectValues( + MicrosoftGraphUser.createFromDiscriminator,); + } else { + result + ..composedType1 = MicrosoftGraphUser() + ..composedType2 = SecondTestEntity(); + } + return result; + } + + MicrosoftGraphUser? composedType1; + SecondTestEntity? composedType2; + String? stringValue; + Iterable? composedType3; + + @override + Map additionalData = {}; + + @override + Map getFieldDeserializers() { + final deserializers = {}; + // Should be other way around en with putIfAbsent + if (composedType1 != null) { + composedType1!.getFieldDeserializers().forEach((k,v) => deserializers.putIfAbsent(k, ()=>v)); + } + if (composedType2 != null) { + composedType2!.getFieldDeserializers().forEach((k,v) => deserializers.putIfAbsent(k, ()=>v)); + } + return deserializers; + } + + @override + void serialize(SerializationWriter writer) { + if (stringValue?.isNotEmpty ?? false) { + writer.writeStringValue(null, stringValue); + } else if (composedType3 != null) { + writer.writeCollectionOfObjectValues(null, composedType3); + } else { + //TODO map should be able to contain null objects + writer.writeObjectValue(null, composedType1, [composedType2!]); + } + } +} diff --git a/packages/kiota_serialization_json/test/intersection_type_test.dart b/packages/kiota_serialization_json/test/intersection_type_test.dart new file mode 100644 index 0000000..60ed6d9 --- /dev/null +++ b/packages/kiota_serialization_json/test/intersection_type_test.dart @@ -0,0 +1,129 @@ +import 'dart:convert'; + +import 'package:kiota_serialization_json/kiota_serialization_json.dart'; +import 'package:test/test.dart'; + +import './intersection_type_mock.dart'; +import 'microsoft_graph_user.dart'; +import 'second_test_entity.dart'; +import 'test_enums.dart'; + +void main() { + group('JsonParseNode for IntersectionModel', () { + test('ParsesIntersectionTypeComplexProperty1', () { + const initialString = + '{"displayName":"McGill","officeLocation":"Montreal", "id": "opaque"}'; + final rawResponse = utf8.encode(initialString); + final parseNode = JsonParseNodeFactory() + .getRootParseNode('application/json', rawResponse); + final result = parseNode + .getObjectValue(IntersectionTypeMock.createFromDiscriminatorValue); + expect(result, isNotNull); + if (result != null) { + expect(result.composedType1, isNotNull); + expect(result.composedType2, isNotNull); + expect(result.composedType3, isNull); + expect(result.stringValue, isNull); + expect(result.composedType1!.id, 'opaque'); + expect(result.composedType2!.displayName, 'McGill'); + } + }); + + test('ParsesIntersectionTypeComplexProperty2', () { + const initialString = + '{"displayName":"McGill","officeLocation":"Montreal", "id": 10}'; + final rawResponse = utf8.encode(initialString); + final parseNode = JsonParseNodeFactory() + .getRootParseNode('application/json', rawResponse); + final result = parseNode + .getObjectValue(IntersectionTypeMock.createFromDiscriminatorValue); + expect(result, isNotNull); + if (result != null) { + expect(result.composedType1, isNotNull); + expect(result.composedType2, isNotNull); + expect(result.composedType3, isNull); + expect(result.stringValue, isNull); + expect(result.composedType2!.displayName, 'McGill'); + expect(result.composedType1!.id, isNull); + } + }); + test('ParsesIntersectionTypeComplexProperty3', () { + const initialString = + '[{"@odata.type":"#microsoft.graph.TestEntity","officeLocation":"Ottawa", "id": "11"}, {"@odata.type":"#microsoft.graph.TestEntity","officeLocation":"Montreal", "id": "10"}]'; + final rawResponse = utf8.encode(initialString); + final parseNode = JsonParseNodeFactory() + .getRootParseNode('application/json', rawResponse); + final result = parseNode + .getObjectValue(IntersectionTypeMock.createFromDiscriminatorValue); + expect(result, isNotNull); + if (result != null) { + expect(result.composedType1, isNull); + expect(result.composedType2, isNull); + expect(result.composedType3, isNotNull); + expect(result.stringValue, isNull); + expect(result.composedType3?.length, 2); + expect(result.composedType3?.first.officeLocation, 'Ottawa'); + } + }); + test('ParsesIntersectionTypeStringValue', () { + const initialString = '"officeLocation"'; + final rawResponse = utf8.encode(initialString); + final parseNode = JsonParseNodeFactory() + .getRootParseNode('application/json', rawResponse); + final result = parseNode + .getObjectValue(IntersectionTypeMock.createFromDiscriminatorValue); + expect(result, isNotNull); + if (result != null) { + expect(result.composedType1, isNull); + expect(result.composedType2, isNull); + expect(result.composedType3, isNull); + expect(result.stringValue, 'officeLocation'); + } + }); + test('SerializeIntersectionTypeStringValue', () { + final writer = JsonSerializationWriter(); + IntersectionTypeMock() + ..stringValue = 'officeLocation' + ..serialize(writer); + final content = writer.getSerializedContent(); + final result = utf8.decode(content); + expect(result, '"officeLocation"'); + }); + test('SerializeIntersectionTypeComplexProperty1', () { + final testEntity1 = MicrosoftGraphUser()..officeLocation='Montreal'..id='opaque'; + final testEntity2 = SecondTestEntity()..displayName='McGill'; + final writer = JsonSerializationWriter(); + IntersectionTypeMock() + ..composedType1=testEntity1 + ..composedType2=testEntity2 + ..serialize(writer); + final content = writer.getSerializedContent(); + final result = utf8.decode(content); + //this one still fails because writeObject needs to use additionalValuesToMerge + // expect(result, '{"id":"opaque","officeLocation":"Montreal","displayName":"McGill"}'); + }); + + test('SerializeIntersectionTypeComplexProperty2', () { + final testEntity2 = SecondTestEntity()..displayName='McGill'..id=10; + final writer = JsonSerializationWriter(); + IntersectionTypeMock() + ..composedType2=testEntity2 + ..serialize(writer); + final content = writer.getSerializedContent(); + final result = utf8.decode(content); + //this one still fails because writeObject needs to use additionalValuesToMerge + //expect(result, '{"displayName":"McGill","id":10}'); + }); + test('SerializeIntersectionTypeComplexProperty3', () { + final testEntity1 = MicrosoftGraphUser()..officeLocation='Montreal'..id='10'..namingEnum=NamingEnum.item2SubItem1; + final testEntity2 = MicrosoftGraphUser()..officeLocation='Ottawa'..id='11'..namingEnum=NamingEnum.item3SubItem1; + final writer = JsonSerializationWriter(); + IntersectionTypeMock() + ..composedType3=[testEntity1, testEntity2] + ..serialize(writer); + final content = writer.getSerializedContent(); + final result = utf8.decode(content); + expect(result, '[{"id":"10","namingEnum":"Item2:SubItem1","officeLocation":"Montreal"},{"id":"11","namingEnum":"Item3:SubItem1","officeLocation":"Ottawa"}]'); + }); + }); +} diff --git a/packages/kiota_serialization_json/test/json_parse_node_test.dart b/packages/kiota_serialization_json/test/json_parse_node_test.dart index 2a4485b..35f6e9c 100644 --- a/packages/kiota_serialization_json/test/json_parse_node_test.dart +++ b/packages/kiota_serialization_json/test/json_parse_node_test.dart @@ -3,7 +3,6 @@ import 'dart:convert'; import 'package:kiota_abstractions/kiota_abstractions.dart'; import 'package:kiota_serialization_json/kiota_serialization_json.dart'; import 'package:test/test.dart'; -import 'package:uuid/uuid.dart'; import 'derived_microsoft_graph_user.dart'; import 'microsoft_graph_user.dart'; @@ -33,7 +32,7 @@ const _testUserJson = r''' "endWorkTime": "17:00:00.0000000", "userPrincipalName": "MeganB@M365x214355.onmicrosoft.com", "birthDay": "1999-08-07", - "id": "48d31887-5fad-4d73-a9f5-3c356e68a038" + "id": "someId" }'''; const _testStudentJson = r''' @@ -126,7 +125,7 @@ void main() { expect(testEntity.additionalData['jobTitle'], 'Auditor'); expect(testEntity.officeLocation, null); - expect(testEntity.id, UuidValue.fromString('48d31887-5fad-4d73-a9f5-3c356e68a038')); + expect(testEntity.id, 'someId'); expect(testEntity.namingEnum, NamingEnum.item2SubItem1); expect(testEntity.workDuration, const Duration(hours: 1)); expect(testEntity.startWorkTime, TimeOnly.fromComponents(8, 0)); diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart index e2121cc..6f1b2ee 100644 --- a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart +++ b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart @@ -2,7 +2,6 @@ import 'dart:convert'; import 'package:kiota_abstractions/kiota_abstractions.dart'; import 'package:kiota_serialization_json/kiota_serialization_json.dart'; import 'package:test/test.dart'; -import 'package:uuid/uuid.dart'; import 'microsoft_graph_group.dart'; import 'microsoft_graph_user.dart'; @@ -39,7 +38,7 @@ void main() { test('writeObject', () { final simpleUser = MicrosoftGraphUser() - ..id=UuidValue.fromString('01924bf0-a3dd-707c-bfb2-5826130b96f2') + ..id='abc' ..createdDateTime=DateTime(2023,12,1,15,15) ..officeLocation='at the desk' ..workDuration=const Duration(hours: 40) @@ -56,7 +55,7 @@ void main() { expect( utf8.decode(writer.getSerializedContent()), - equals('{"id":"01924bf0-a3dd-707c-bfb2-5826130b96f2","createdDateTime":"2023-12-01T15:15:00.000","officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":1.7,"startWorkTime":"06:00:00","active":true,"numbers":[2,3,5],"a":"some value","b":12,"c":false}'), + equals('{"id":"abc","createdDateTime":"2023-12-01T15:15:00.000","officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":1.7,"startWorkTime":"06:00:00","active":true,"numbers":[2,3,5],"a":"some value","b":12,"c":false}'), ); }); diff --git a/packages/kiota_serialization_json/test/microsoft_graph_user.dart b/packages/kiota_serialization_json/test/microsoft_graph_user.dart index 51b365d..a05712e 100644 --- a/packages/kiota_serialization_json/test/microsoft_graph_user.dart +++ b/packages/kiota_serialization_json/test/microsoft_graph_user.dart @@ -1,5 +1,4 @@ import 'package:kiota_abstractions/kiota_abstractions.dart'; -import 'package:uuid/uuid.dart'; import 'derived_microsoft_graph_user.dart'; import 'test_enums.dart'; @@ -27,7 +26,7 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { @override Map additionalData = {}; - UuidValue? id; + String? id; NamingEnum? namingEnum; DateOnly? birthDay; TimeOnly? startWorkTime; @@ -43,7 +42,7 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { @override void serialize(SerializationWriter writer) { writer - ..writeUuidValue('id', id) + ..writeStringValue('id', id) ..writeEnumValue( 'namingEnum', namingEnum, _namingEnumSerializer,) ..writeDateTimeValue('createdDateTime', createdDateTime) @@ -62,7 +61,7 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { @override Map getFieldDeserializers() { return { - 'id': (node) => id = node.getGuidValue(), + 'id': (node) => id = node.getStringValue(), 'namingEnum': (node) => namingEnum = node.getEnumValue(_namingEnumFactory), 'createdDateTime': (node) => createdDateTime = node.getDateTimeValue(), diff --git a/packages/kiota_serialization_json/test/second_test_entity.dart b/packages/kiota_serialization_json/test/second_test_entity.dart new file mode 100644 index 0000000..f366f44 --- /dev/null +++ b/packages/kiota_serialization_json/test/second_test_entity.dart @@ -0,0 +1,34 @@ +import 'package:kiota_abstractions/kiota_abstractions.dart'; + +class SecondTestEntity extends Parsable implements AdditionalDataHolder { + + SecondTestEntity(); + + factory SecondTestEntity.createFromDiscriminatorValue(ParseNode parseNode) { + return SecondTestEntity(); + } + + @override + Map additionalData = {}; + int? id; + String? displayName; + int? failureRate; + + @override + Map getFieldDeserializers() { + return { + 'id': (node) => id = node.getIntValue(), + 'displayName': (node) => + displayName = node.getStringValue(), + 'failureRate': (node) => failureRate = node.getIntValue(), + }; + } + + @override + void serialize(SerializationWriter writer) { + writer..writeStringValue("displayName", displayName) + ..writeIntValue("id", id) + ..writeIntValue("failureRate", failureRate) + ..writeAdditionalData(additionalData); + } +} From 9054909c5c0451fe03c75b9f06e72364e7ddc790 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 16 Oct 2024 09:22:56 +0200 Subject: [PATCH 48/69] also write additional values when writing object --- .../serialization/serialization_writer.dart | 2 +- .../lib/src/form_serialization_writer.dart | 12 +++--- .../lib/src/json_serialization_writer.dart | 40 ++++++++++++------- .../test/intersection_type_mock.dart | 3 +- .../test/intersection_type_test.dart | 6 +-- .../lib/src/text_serialization_writer.dart | 2 +- 6 files changed, 38 insertions(+), 27 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/serialization/serialization_writer.dart b/packages/kiota_abstractions/lib/src/serialization/serialization_writer.dart index 6b954b4..1daa7ab 100644 --- a/packages/kiota_abstractions/lib/src/serialization/serialization_writer.dart +++ b/packages/kiota_abstractions/lib/src/serialization/serialization_writer.dart @@ -71,7 +71,7 @@ abstract class SerializationWriter { void writeObjectValue( String? key, T? value, [ - Iterable? additionalValuesToMerge, + Iterable? additionalValuesToMerge, ]); /// Writes the specified enum value to the buffer with an optional given diff --git a/packages/kiota_serialization_form/lib/src/form_serialization_writer.dart b/packages/kiota_serialization_form/lib/src/form_serialization_writer.dart index 9fd165f..90e89c2 100644 --- a/packages/kiota_serialization_form/lib/src/form_serialization_writer.dart +++ b/packages/kiota_serialization_form/lib/src/form_serialization_writer.dart @@ -146,7 +146,7 @@ class FormSerializationWriter implements SerializationWriter { void writeObjectValue( String? key, T? value, [ - Iterable? additionalValuesToMerge, + Iterable? additionalValuesToMerge, ]) { if (writingObject) { throw UnsupportedError( @@ -168,12 +168,14 @@ class FormSerializationWriter implements SerializationWriter { if (additionalValuesToMerge != null) { for (final additionalValue in additionalValuesToMerge) { - onBeforeObjectSerialization?.call(additionalValue); - onStartObjectSerialization?.call(additionalValue, this); + if(additionalValue != null){ + onBeforeObjectSerialization?.call(additionalValue); + onStartObjectSerialization?.call(additionalValue, this); - additionalValue.serialize(this); + additionalValue.serialize(this); - onAfterObjectSerialization?.call(additionalValue); + onAfterObjectSerialization?.call(additionalValue); + } } } diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index 2b7eeb5..9d9fa5a 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -174,32 +174,44 @@ class JsonSerializationWriter implements SerializationWriter { void writeObjectValue( String? key, T? value, [ - Iterable? additionalValuesToMerge, + Iterable? additionalValuesToMerge, ]) { - if(value == null){ + if(value == null && additionalValuesToMerge == null){ return; } - else if(key == null){ + if(value != null){ onBeforeObjectSerialization?.call(value); - _buffer.add(openingObject); - onStartObjectSerialization?.call(value, this); - value.serialize(this); - removeSeparator(); - _buffer.add(closingObject); - onAfterObjectSerialization?.call(value); - _buffer.add(separator); + } + + if(key == null){ + _buffer.add(openingObject); } else { - onBeforeObjectSerialization?.call(value); _buffer.add('"$key":$openingObject'); + } + if(value != null){ onStartObjectSerialization?.call(value, this); value.serialize(this); - removeSeparator(); - _buffer.add(closingObject); + } + if (additionalValuesToMerge != null) { + for (final additionalValue in additionalValuesToMerge) { + if(additionalValue != null){ + onBeforeObjectSerialization?.call(additionalValue); + onStartObjectSerialization?.call(additionalValue, this); + + additionalValue.serialize(this); + + onAfterObjectSerialization?.call(additionalValue); + } + } + } + removeSeparator(); + _buffer.add(closingObject); + if(value != null){ onAfterObjectSerialization?.call(value); - _buffer.add(separator); } + _buffer.add(separator); } @override diff --git a/packages/kiota_serialization_json/test/intersection_type_mock.dart b/packages/kiota_serialization_json/test/intersection_type_mock.dart index 991ee8d..a20012e 100644 --- a/packages/kiota_serialization_json/test/intersection_type_mock.dart +++ b/packages/kiota_serialization_json/test/intersection_type_mock.dart @@ -54,8 +54,7 @@ class IntersectionTypeMock extends Parsable implements AdditionalDataHolder { } else if (composedType3 != null) { writer.writeCollectionOfObjectValues(null, composedType3); } else { - //TODO map should be able to contain null objects - writer.writeObjectValue(null, composedType1, [composedType2!]); + writer.writeObjectValue(null, composedType1, [composedType2]); } } } diff --git a/packages/kiota_serialization_json/test/intersection_type_test.dart b/packages/kiota_serialization_json/test/intersection_type_test.dart index 60ed6d9..8207357 100644 --- a/packages/kiota_serialization_json/test/intersection_type_test.dart +++ b/packages/kiota_serialization_json/test/intersection_type_test.dart @@ -99,8 +99,7 @@ void main() { ..serialize(writer); final content = writer.getSerializedContent(); final result = utf8.decode(content); - //this one still fails because writeObject needs to use additionalValuesToMerge - // expect(result, '{"id":"opaque","officeLocation":"Montreal","displayName":"McGill"}'); + expect(result, '{"id":"opaque","officeLocation":"Montreal","displayName":"McGill"}'); }); test('SerializeIntersectionTypeComplexProperty2', () { @@ -111,8 +110,7 @@ void main() { ..serialize(writer); final content = writer.getSerializedContent(); final result = utf8.decode(content); - //this one still fails because writeObject needs to use additionalValuesToMerge - //expect(result, '{"displayName":"McGill","id":10}'); + expect(result, '{"displayName":"McGill","id":10}'); }); test('SerializeIntersectionTypeComplexProperty3', () { final testEntity1 = MicrosoftGraphUser()..officeLocation='Montreal'..id='10'..namingEnum=NamingEnum.item2SubItem1; diff --git a/packages/kiota_serialization_text/lib/src/text_serialization_writer.dart b/packages/kiota_serialization_text/lib/src/text_serialization_writer.dart index d08923a..544f371 100644 --- a/packages/kiota_serialization_text/lib/src/text_serialization_writer.dart +++ b/packages/kiota_serialization_text/lib/src/text_serialization_writer.dart @@ -92,7 +92,7 @@ class TextSerializationWriter implements SerializationWriter { void writeObjectValue( String? key, T? value, [ - Iterable? additionalValuesToMerge, + Iterable? additionalValuesToMerge, ]) { throw _noStructuredDataError(); } From 4b55c7b97ad916add58cda78a134c93be107191c Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 16 Oct 2024 10:28:00 +0200 Subject: [PATCH 49/69] Added tests for union type --- .../test/intersection_type_mock.dart | 1 - .../test/union_type_mock.dart | 63 +++++++++ .../test/union_type_test.dart | 125 ++++++++++++++++++ 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 packages/kiota_serialization_json/test/union_type_mock.dart create mode 100644 packages/kiota_serialization_json/test/union_type_test.dart diff --git a/packages/kiota_serialization_json/test/intersection_type_mock.dart b/packages/kiota_serialization_json/test/intersection_type_mock.dart index a20012e..9a74af5 100644 --- a/packages/kiota_serialization_json/test/intersection_type_mock.dart +++ b/packages/kiota_serialization_json/test/intersection_type_mock.dart @@ -37,7 +37,6 @@ class IntersectionTypeMock extends Parsable implements AdditionalDataHolder { @override Map getFieldDeserializers() { final deserializers = {}; - // Should be other way around en with putIfAbsent if (composedType1 != null) { composedType1!.getFieldDeserializers().forEach((k,v) => deserializers.putIfAbsent(k, ()=>v)); } diff --git a/packages/kiota_serialization_json/test/union_type_mock.dart b/packages/kiota_serialization_json/test/union_type_mock.dart new file mode 100644 index 0000000..2b38a75 --- /dev/null +++ b/packages/kiota_serialization_json/test/union_type_mock.dart @@ -0,0 +1,63 @@ +import 'package:kiota_abstractions/kiota_abstractions.dart'; + +import './microsoft_graph_user.dart'; +import './second_test_entity.dart'; + +class UnionTypeMock extends Parsable implements AdditionalDataHolder { + UnionTypeMock(); + + factory UnionTypeMock.createFromDiscriminatorValue( + ParseNode parseNode, + ) { + final result = UnionTypeMock(); + final discriminator = + parseNode.getChildNode('@odata.type')?.getStringValue(); + if ('#microsoft.graph.testEntity' == discriminator) { + result.composedType1 = MicrosoftGraphUser(); + } else if ('#microsoft.graph.secondTestEntity' == discriminator) { + result.composedType2 = SecondTestEntity(); + } else if (parseNode.getStringValue() is String) { + result.stringValue = parseNode.getStringValue(); + } else if (parseNode + .getCollectionOfObjectValues( + MicrosoftGraphUser.createFromDiscriminator) + .isNotEmpty) { + result.composedType3 = + parseNode.getCollectionOfObjectValues( + MicrosoftGraphUser.createFromDiscriminator); + } + return result; + } + + MicrosoftGraphUser? composedType1; + SecondTestEntity? composedType2; + String? stringValue; + Iterable? composedType3; + + @override + Map additionalData = {}; + + @override + Map getFieldDeserializers() { + if (composedType1 != null) { + return composedType1!.getFieldDeserializers(); + } + if (composedType2 != null) { + return composedType2!.getFieldDeserializers(); + } + return {}; + } + + @override + void serialize(SerializationWriter writer) { + if (composedType1 != null) { + writer.writeObjectValue(null, composedType1); + } else if (composedType2 != null) { + writer.writeObjectValue(null, composedType2); + } else if (stringValue != null) { + writer.writeStringValue(null, stringValue); + } else if (composedType3 != null) { + writer.writeCollectionOfObjectValues(null, composedType3); + } + } +} diff --git a/packages/kiota_serialization_json/test/union_type_test.dart b/packages/kiota_serialization_json/test/union_type_test.dart new file mode 100644 index 0000000..0885a3a --- /dev/null +++ b/packages/kiota_serialization_json/test/union_type_test.dart @@ -0,0 +1,125 @@ +import 'dart:convert'; + +import 'package:kiota_serialization_json/kiota_serialization_json.dart'; +import 'package:test/test.dart'; + +import 'microsoft_graph_user.dart'; +import 'second_test_entity.dart'; +import 'union_type_mock.dart'; + +void main() { + group('JsonParseNode for UnionModel', () { + test('ParsesUnionTypeComplexProperty1', () { + const initialString = + '{"@odata.type":"#microsoft.graph.testEntity","officeLocation":"Montreal", "id": "opaque"}'; + final rawResponse = utf8.encode(initialString); + final parseNode = JsonParseNodeFactory() + .getRootParseNode('application/json', rawResponse); + final result = parseNode + .getObjectValue(UnionTypeMock.createFromDiscriminatorValue); + expect(result, isNotNull); + if (result != null) { + expect(result.composedType1, isNotNull); + expect(result.composedType2, isNull); + expect(result.composedType3, isNull); + expect(result.stringValue, isNull); + expect(result.composedType1!.id, 'opaque'); + expect(result.composedType1!.officeLocation, 'Montreal'); + } + }); + + test('ParsesUnionTypeComplexProperty2', () { + const initialString = + '{"@odata.type":"#microsoft.graph.secondTestEntity","officeLocation":"Montreal", "id": 10}'; + final rawResponse = utf8.encode(initialString); + final parseNode = JsonParseNodeFactory() + .getRootParseNode('application/json', rawResponse); + final result = parseNode + .getObjectValue(UnionTypeMock.createFromDiscriminatorValue); + expect(result, isNotNull); + if (result != null) { + expect(result.composedType1, isNull); + expect(result.composedType2, isNotNull); + expect(result.composedType3, isNull); + expect(result.stringValue, isNull); + expect(result.composedType2!.id, 10); + } + }); + test('ParsesUnionTypeComplexProperty3', () { + const initialString = + '[{"@odata.type":"#microsoft.graph.TestEntity","officeLocation":"Ottawa", "id": "11"}, {"@odata.type":"#microsoft.graph.TestEntity","officeLocation":"Montreal", "id": "10"}]'; + final rawResponse = utf8.encode(initialString); + final parseNode = JsonParseNodeFactory() + .getRootParseNode('application/json', rawResponse); + final result = parseNode + .getObjectValue(UnionTypeMock.createFromDiscriminatorValue); + expect(result, isNotNull); + if (result != null) { + expect(result.composedType1, isNull); + expect(result.composedType2, isNull); + expect(result.composedType3, isNotNull); + expect(result.stringValue, isNull); + expect(result.composedType3?.length, 2); + expect(result.composedType3?.first.id, '11'); + } + }); + test('ParsesUnionTypeStringValue', () { + const initialString = '"officeLocation"'; + final rawResponse = utf8.encode(initialString); + final parseNode = JsonParseNodeFactory() + .getRootParseNode('application/json', rawResponse); + final result = parseNode + .getObjectValue(UnionTypeMock.createFromDiscriminatorValue); + expect(result, isNotNull); + if (result != null) { + expect(result.composedType1, isNull); + expect(result.composedType2, isNull); + expect(result.composedType3, isNull); + expect(result.stringValue, 'officeLocation'); + } + }); + test('SerializeUnionTypeStringValue', () { + final writer = JsonSerializationWriter(); + UnionTypeMock() + ..stringValue = 'officeLocation' + ..serialize(writer); + final content = writer.getSerializedContent(); + final result = utf8.decode(content); + expect(result, '"officeLocation"'); + }); + test('SerializeUnionTypeComplexProperty1', () { + final testEntity1 = MicrosoftGraphUser()..officeLocation='Montreal'..id='opaque'; + final testEntity2 = SecondTestEntity()..displayName='McGill'; + final writer = JsonSerializationWriter(); + UnionTypeMock() + ..composedType1=testEntity1 + ..composedType2=testEntity2 + ..serialize(writer); + final content = writer.getSerializedContent(); + final result = utf8.decode(content); + expect(result, '{"id":"opaque","officeLocation":"Montreal"}'); + }); + + test('SerializeUnionTypeComplexProperty2', () { + final testEntity2 = SecondTestEntity()..displayName='McGill'..id=10; + final writer = JsonSerializationWriter(); + UnionTypeMock() + ..composedType2=testEntity2 + ..serialize(writer); + final content = writer.getSerializedContent(); + final result = utf8.decode(content); + expect(result, '{"displayName":"McGill","id":10}'); + }); + test('SerializeUnionComplexProperty3', () { + final testEntity1 = MicrosoftGraphUser()..officeLocation='Montreal'..id='10'; + final testEntity2 = MicrosoftGraphUser()..officeLocation='Ottawa'..id='11'; + final writer = JsonSerializationWriter(); + UnionTypeMock() + ..composedType3=[testEntity1, testEntity2] + ..serialize(writer); + final content = writer.getSerializedContent(); + final result = utf8.decode(content); + expect(result, '[{"id":"10","officeLocation":"Montreal"},{"id":"11","officeLocation":"Ottawa"}]'); + }); + }); +} From 8ec83229458f355a0f47472e1044f428415d88fb Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Fri, 18 Oct 2024 14:16:24 +0200 Subject: [PATCH 50/69] Added tests for json factories, some formatting --- .../lib/src/json_parse_node.dart | 11 +- .../lib/src/json_parse_node_factory.dart | 1 - .../lib/src/json_serialization_writer.dart | 181 +++++++++--------- .../test/derived_microsoft_graph_user.dart | 4 +- .../test/intersection_type_mock.dart | 19 +- .../test/intersection_type_test.dart | 34 ++-- .../test/json_parse_node_factory_test.dart | 24 +++ .../test/json_parse_node_test.dart | 13 +- ...son_serialization_writer_factory_test.dart | 22 +++ .../test/json_serialization_writer_test.dart | 79 ++++---- .../test/microsoft_graph_group.dart | 9 +- .../test/microsoft_graph_user.dart | 13 +- .../test/second_test_entity.dart | 19 +- .../test/union_type_test.dart | 45 +++-- .../test/untyped_test_entity.dart | 23 +-- 15 files changed, 286 insertions(+), 211 deletions(-) create mode 100644 packages/kiota_serialization_json/test/json_parse_node_factory_test.dart create mode 100644 packages/kiota_serialization_json/test/json_serialization_writer_factory_test.dart diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index f30c9ed..5f6cdaa 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -130,10 +130,10 @@ class JsonParseNode implements ParseNode { } void _assignFieldValues(T item) { - if (_node is! Map){ + if (_node is! Map) { return; } - + onBeforeAssignFieldValues?.call(item); final itemAdditionalData = item is AdditionalDataHolder @@ -184,10 +184,9 @@ class JsonParseNode implements ParseNode { final fieldKey = entry.key as String; final fieldValue = entry.value; final childNode = JsonParseNode(fieldValue) - ..onBeforeAssignFieldValues = onBeforeAssignFieldValues - ..onAfterAssignFieldValues = onAfterAssignFieldValues; - propertiesMap[fieldKey] = - childNode.getUntypedValue(fieldValue)!; + ..onBeforeAssignFieldValues = onBeforeAssignFieldValues + ..onAfterAssignFieldValues = onAfterAssignFieldValues; + propertiesMap[fieldKey] = childNode.getUntypedValue(fieldValue)!; } return UntypedObject(propertiesMap); } diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node_factory.dart b/packages/kiota_serialization_json/lib/src/json_parse_node_factory.dart index 986fe35..7d8debe 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node_factory.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node_factory.dart @@ -1,6 +1,5 @@ part of '../kiota_serialization_json.dart'; - class JsonParseNodeFactory implements ParseNodeFactory { @override ParseNode getRootParseNode(String contentType, Uint8List content) { diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index 9d9fa5a..a26a7f8 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -26,13 +26,10 @@ class JsonSerializationWriter implements SerializationWriter { @override void writeAdditionalData(Map value) { - for(final entry in value.entries){ - if(entry.value is bool || entry.value is int || entry.value is double) - { + for (final entry in value.entries) { + if (entry.value is bool || entry.value is int || entry.value is double) { _buffer.add('"${entry.key}":${entry.value}'); - } - else - { + } else { _buffer.add('"${entry.key}":"${_getAnyValue(entry.value as Object)}"'); } _buffer.add(separator); @@ -55,91 +52,85 @@ class JsonSerializationWriter implements SerializationWriter { Iterable? values, EnumSerializer serializer, ) { - if(values == null || values.isEmpty){ + if (values == null || values.isEmpty) { return; - } - else{ - final writeAsObject = _buffer.isEmpty; - final opening = writeAsObject? openingObject : ''; - _buffer.add('$opening"$key":$openingArray'); - var first = true; - for (final value in values) - { - if(!first){ - _buffer.add(separator); - } - first = false; - _buffer.add('"${serializer(value)}"'); + } else { + final writeAsObject = _buffer.isEmpty; + final opening = writeAsObject ? openingObject : ''; + _buffer.add('$opening"$key":$openingArray'); + var first = true; + for (final value in values) { + if (!first) { + _buffer.add(separator); } - _buffer.add(closingArray); - if(writeAsObject){ - _buffer.add(closingObject); + first = false; + _buffer.add('"${serializer(value)}"'); + } + _buffer.add(closingArray); + if (writeAsObject) { + _buffer.add(closingObject); + } + _buffer.add(separator); } - _buffer.add(separator); - }} + } @override void writeCollectionOfObjectValues( String? key, Iterable? values, ) { - if(values == null || values.isEmpty){ + if (values == null || values.isEmpty) { return; - } - else{ - if(key?.isEmpty?? true){ + } else { + if (key?.isEmpty ?? true) { _buffer.add(openingArray); - } - else{ + } else { _buffer.add('"$key":$openingArray'); } - var first = true; - for (final value in values) - { - if(!first){ - _buffer.add(separator); - } - first = false; - _buffer.add(openingObject); - value.serialize(this); - removeSeparator(); - _buffer.add(closingObject); - } - _buffer..add(closingArray) - ..add(separator); - }} + var first = true; + for (final value in values) { + if (!first) { + _buffer.add(separator); + } + first = false; + _buffer.add(openingObject); + value.serialize(this); + removeSeparator(); + _buffer.add(closingObject); + } + _buffer + ..add(closingArray) + ..add(separator); + } + } @override void writeCollectionOfPrimitiveValues(String? key, Iterable? values) { - if(values == null || values.isEmpty){ + if (values == null || values.isEmpty) { return; - } - else{ - final writeAsObject = _buffer.isEmpty; - final opening = writeAsObject? openingObject : ''; - _buffer.add('$opening"$key":$openingArray'); - var first = true; - for (final value in values) - { - if(!first){ - _buffer.add(separator); - } - first = false; - if(value is bool || value is int || value is double) - { - _buffer.add('$value'); - } - else - { - _buffer.add('"${_getAnyValue(value!)}"'); - } + } else { + final writeAsObject = _buffer.isEmpty; + final opening = writeAsObject ? openingObject : ''; + _buffer.add('$opening"$key":$openingArray'); + var first = true; + for (final value in values) { + if (!first) { + _buffer.add(separator); + } + first = false; + if (value is bool || value is int || value is double) { + _buffer.add('$value'); + } else { + _buffer.add('"${_getAnyValue(value!)}"'); } - _buffer.add(closingArray); - if(writeAsObject){ - _buffer.add(closingObject); + } + _buffer.add(closingArray); + if (writeAsObject) { + _buffer.add(closingObject); + } + _buffer.add(separator); } - _buffer.add(separator); - }} + } @override void writeDateTimeValue(String? key, DateTime? value) { @@ -176,27 +167,25 @@ class JsonSerializationWriter implements SerializationWriter { T? value, [ Iterable? additionalValuesToMerge, ]) { - if(value == null && additionalValuesToMerge == null){ + if (value == null && additionalValuesToMerge == null) { return; } - if(value != null){ + if (value != null) { onBeforeObjectSerialization?.call(value); } - if(key == null){ - _buffer.add(openingObject); - } - else - { + if (key == null) { + _buffer.add(openingObject); + } else { _buffer.add('"$key":$openingObject'); } - if(value != null){ + if (value != null) { onStartObjectSerialization?.call(value, this); value.serialize(this); } if (additionalValuesToMerge != null) { for (final additionalValue in additionalValuesToMerge) { - if(additionalValue != null){ + if (additionalValue != null) { onBeforeObjectSerialization?.call(additionalValue); onStartObjectSerialization?.call(additionalValue, this); @@ -208,7 +197,7 @@ class JsonSerializationWriter implements SerializationWriter { } removeSeparator(); _buffer.add(closingObject); - if(value != null){ + if (value != null) { onAfterObjectSerialization?.call(value); } _buffer.add(separator); @@ -220,26 +209,28 @@ class JsonSerializationWriter implements SerializationWriter { if (value?.isEmpty ?? true) { return; } - if(key?.isEmpty ?? true){ - _buffer..add('"$value"') - ..add(separator); - } - else{ - _buffer..add('"$key":"$value"') - ..add(separator); + if (key?.isEmpty ?? true) { + _buffer + ..add('"$value"') + ..add(separator); + } else { + _buffer + ..add('"$key":"$value"') + ..add(separator); } } void writeUnquotedValue(String? key, Object? value) { - if (key?.isEmpty ?? true) { + if (key?.isEmpty ?? true) { return; } // if the value is null or empty, we don't write anything if (value == null) { return; } - _buffer..add('"$key":$value') - ..add(separator); + _buffer + ..add('"$key":$value') + ..add(separator); } @override @@ -262,8 +253,8 @@ class JsonSerializationWriter implements SerializationWriter { writeStringValue(key, value?.uuid); } - void removeSeparator(){ - if(_buffer.last == separator){ + void removeSeparator() { + if (_buffer.last == separator) { _buffer.removeLast(); } } @@ -281,7 +272,7 @@ class JsonSerializationWriter implements SerializationWriter { case final TimeOnly t: return t.toRfc3339String(); default: - return value.toString(); + return value.toString(); } } } diff --git a/packages/kiota_serialization_json/test/derived_microsoft_graph_user.dart b/packages/kiota_serialization_json/test/derived_microsoft_graph_user.dart index 03d712d..df2c331 100644 --- a/packages/kiota_serialization_json/test/derived_microsoft_graph_user.dart +++ b/packages/kiota_serialization_json/test/derived_microsoft_graph_user.dart @@ -16,8 +16,8 @@ class DerivedMicrosoftGraphUser extends MicrosoftGraphUser { @override Map getFieldDeserializers() { final parentDeserializers = super.getFieldDeserializers(); - parentDeserializers['enrolmentDate'] = (node) => enrolmentDate = node.getDateOnlyValue(); + parentDeserializers['enrolmentDate'] = + (node) => enrolmentDate = node.getDateOnlyValue(); return parentDeserializers; } - } diff --git a/packages/kiota_serialization_json/test/intersection_type_mock.dart b/packages/kiota_serialization_json/test/intersection_type_mock.dart index 9a74af5..fabf4ea 100644 --- a/packages/kiota_serialization_json/test/intersection_type_mock.dart +++ b/packages/kiota_serialization_json/test/intersection_type_mock.dart @@ -7,17 +7,20 @@ class IntersectionTypeMock extends Parsable implements AdditionalDataHolder { IntersectionTypeMock(); factory IntersectionTypeMock.createFromDiscriminatorValue( - ParseNode parseNode,) { + ParseNode parseNode, + ) { final result = IntersectionTypeMock(); if (parseNode.getStringValue() != null) { result.stringValue = parseNode.getStringValue(); } else if (parseNode .getCollectionOfObjectValues( - MicrosoftGraphUser.createFromDiscriminator,) + MicrosoftGraphUser.createFromDiscriminator, + ) .isNotEmpty) { result.composedType3 = parseNode.getCollectionOfObjectValues( - MicrosoftGraphUser.createFromDiscriminator,); + MicrosoftGraphUser.createFromDiscriminator, + ); } else { result ..composedType1 = MicrosoftGraphUser() @@ -38,11 +41,15 @@ class IntersectionTypeMock extends Parsable implements AdditionalDataHolder { Map getFieldDeserializers() { final deserializers = {}; if (composedType1 != null) { - composedType1!.getFieldDeserializers().forEach((k,v) => deserializers.putIfAbsent(k, ()=>v)); + composedType1! + .getFieldDeserializers() + .forEach((k, v) => deserializers.putIfAbsent(k, () => v)); } if (composedType2 != null) { - composedType2!.getFieldDeserializers().forEach((k,v) => deserializers.putIfAbsent(k, ()=>v)); - } + composedType2! + .getFieldDeserializers() + .forEach((k, v) => deserializers.putIfAbsent(k, () => v)); + } return deserializers; } diff --git a/packages/kiota_serialization_json/test/intersection_type_test.dart b/packages/kiota_serialization_json/test/intersection_type_test.dart index 8207357..842f134 100644 --- a/packages/kiota_serialization_json/test/intersection_type_test.dart +++ b/packages/kiota_serialization_json/test/intersection_type_test.dart @@ -90,38 +90,50 @@ void main() { expect(result, '"officeLocation"'); }); test('SerializeIntersectionTypeComplexProperty1', () { - final testEntity1 = MicrosoftGraphUser()..officeLocation='Montreal'..id='opaque'; - final testEntity2 = SecondTestEntity()..displayName='McGill'; + final testEntity1 = MicrosoftGraphUser() + ..officeLocation = 'Montreal' + ..id = 'opaque'; + final testEntity2 = SecondTestEntity()..displayName = 'McGill'; final writer = JsonSerializationWriter(); IntersectionTypeMock() - ..composedType1=testEntity1 - ..composedType2=testEntity2 + ..composedType1 = testEntity1 + ..composedType2 = testEntity2 ..serialize(writer); final content = writer.getSerializedContent(); final result = utf8.decode(content); - expect(result, '{"id":"opaque","officeLocation":"Montreal","displayName":"McGill"}'); + expect(result, + '{"id":"opaque","officeLocation":"Montreal","displayName":"McGill"}'); }); test('SerializeIntersectionTypeComplexProperty2', () { - final testEntity2 = SecondTestEntity()..displayName='McGill'..id=10; + final testEntity2 = SecondTestEntity() + ..displayName = 'McGill' + ..id = 10; final writer = JsonSerializationWriter(); IntersectionTypeMock() - ..composedType2=testEntity2 + ..composedType2 = testEntity2 ..serialize(writer); final content = writer.getSerializedContent(); final result = utf8.decode(content); expect(result, '{"displayName":"McGill","id":10}'); }); test('SerializeIntersectionTypeComplexProperty3', () { - final testEntity1 = MicrosoftGraphUser()..officeLocation='Montreal'..id='10'..namingEnum=NamingEnum.item2SubItem1; - final testEntity2 = MicrosoftGraphUser()..officeLocation='Ottawa'..id='11'..namingEnum=NamingEnum.item3SubItem1; + final testEntity1 = MicrosoftGraphUser() + ..officeLocation = 'Montreal' + ..id = '10' + ..namingEnum = NamingEnum.item2SubItem1; + final testEntity2 = MicrosoftGraphUser() + ..officeLocation = 'Ottawa' + ..id = '11' + ..namingEnum = NamingEnum.item3SubItem1; final writer = JsonSerializationWriter(); IntersectionTypeMock() - ..composedType3=[testEntity1, testEntity2] + ..composedType3 = [testEntity1, testEntity2] ..serialize(writer); final content = writer.getSerializedContent(); final result = utf8.decode(content); - expect(result, '[{"id":"10","namingEnum":"Item2:SubItem1","officeLocation":"Montreal"},{"id":"11","namingEnum":"Item3:SubItem1","officeLocation":"Ottawa"}]'); + expect(result, + '[{"id":"10","namingEnum":"Item2:SubItem1","officeLocation":"Montreal"},{"id":"11","namingEnum":"Item3:SubItem1","officeLocation":"Ottawa"}]'); }); }); } diff --git a/packages/kiota_serialization_json/test/json_parse_node_factory_test.dart b/packages/kiota_serialization_json/test/json_parse_node_factory_test.dart new file mode 100644 index 0000000..b8d4ab1 --- /dev/null +++ b/packages/kiota_serialization_json/test/json_parse_node_factory_test.dart @@ -0,0 +1,24 @@ +import 'dart:convert'; + +import 'package:kiota_serialization_json/kiota_serialization_json.dart'; +import 'package:test/test.dart'; + +void main() { + group('JsonParseNodeFactoryTest', () { + test('getParseNodeForJsonContentType', () { + final json = utf8.encode('{"key":"value"}'); + final factory = JsonParseNodeFactory(); + final JsonParseNode = + factory.getRootParseNode(factory.validContentType, json); + expect(JsonParseNode, isNotNull); + }); + + test('testThrowsExceptionForInvalidContentType', () { + const streamContentType = 'application/octet-stream'; + final json = utf8.encode('{"key":"value"}'); + final factory = JsonParseNodeFactory(); + expect(() => factory.getRootParseNode(streamContentType, json), + throwsArgumentError); + }); + }); +} diff --git a/packages/kiota_serialization_json/test/json_parse_node_test.dart b/packages/kiota_serialization_json/test/json_parse_node_test.dart index 35f6e9c..ce1b77f 100644 --- a/packages/kiota_serialization_json/test/json_parse_node_test.dart +++ b/packages/kiota_serialization_json/test/json_parse_node_test.dart @@ -166,9 +166,10 @@ void main() { } }); test('Get enumcollection from json', () { - final jsonParseNode = JsonParseNode(jsonDecode(_testCollectionOfEnumsJson)); - final testCollection = jsonParseNode - .getCollectionOfEnumValues((value)=> NamingEnum.values.where((ne) => ne.value == value).firstOrNull); + final jsonParseNode = + JsonParseNode(jsonDecode(_testCollectionOfEnumsJson)); + final testCollection = jsonParseNode.getCollectionOfEnumValues((value) => + NamingEnum.values.where((ne) => ne.value == value).firstOrNull); expect(testCollection, isNotNull); expect(testCollection.length, 2); @@ -178,12 +179,12 @@ void main() { test('Get collection of primitive values from json', () { final jsonParseNode = JsonParseNode(jsonDecode('[2,3,5]')); - final testCollection = jsonParseNode - .getCollectionOfPrimitiveValues(); + final testCollection = + jsonParseNode.getCollectionOfPrimitiveValues(); expect(testCollection, isNotNull); expect(testCollection.length, 3); - expect(testCollection.first,2); + expect(testCollection.first, 2); expect(testCollection.last, 5); }); }); diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_factory_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_factory_test.dart new file mode 100644 index 0000000..e51afda --- /dev/null +++ b/packages/kiota_serialization_json/test/json_serialization_writer_factory_test.dart @@ -0,0 +1,22 @@ +import 'dart:convert'; +import 'package:kiota_abstractions/kiota_abstractions.dart'; +import 'package:kiota_serialization_json/kiota_serialization_json.dart'; +import 'package:test/test.dart'; + +void main() { + group('JsonSerializationWriterFactory', () { + test('getWriterForJsonContentType', () { + final factory = JsonSerializationWriterFactory(); + final jsonWriter = + factory.getSerializationWriter(factory.validContentType); + expect(jsonWriter, isNotNull); + }); + + test('testThrowsExceptionForInvalidContentType', () { + const streamContentType = 'application/octet-stream'; + final factory = JsonSerializationWriterFactory(); + expect(() => factory.getSerializationWriter(streamContentType), + throwsArgumentError); + }); + }); +} diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart index 6f1b2ee..dcd051f 100644 --- a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart +++ b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart @@ -6,7 +6,6 @@ import 'package:test/test.dart'; import 'microsoft_graph_group.dart'; import 'microsoft_graph_user.dart'; - String? _httpMethodEnumSerializer(HttpMethod? value) => value?.name; void main() { @@ -24,11 +23,12 @@ void main() { equals('{"key":["get","post","patch"]}'), ); }); - test('writeCollectionOfPrimitiveValues', () { + test('writeCollectionOfPrimitiveValues', () { final writer = JsonSerializationWriter() ..writeCollectionOfPrimitiveValues( 'intlist', - [1,2,3],); + [1, 2, 3], + ); expect( utf8.decode(writer.getSerializedContent()), @@ -36,52 +36,59 @@ void main() { ); }); - test('writeObject', () { - final simpleUser = MicrosoftGraphUser() - ..id='abc' - ..createdDateTime=DateTime(2023,12,1,15,15) - ..officeLocation='at the desk' - ..workDuration=const Duration(hours: 40) - ..birthDay=DateOnly.fromDateTime(DateTime.parse('2024-10-01 00:00:00')) - ..heightInMetres=1.7 - ..startWorkTime=TimeOnly.fromDateTimeString('06:00') - ..active=true - ..numbers=[2,3,5] - ..additionalData={'a':'some value', 'b': 12, 'c' : false}; - + test('writeObject', () { + final simpleUser = MicrosoftGraphUser() + ..id = 'abc' + ..createdDateTime = DateTime(2023, 12, 1, 15, 15) + ..officeLocation = 'at the desk' + ..workDuration = const Duration(hours: 40) + ..birthDay = + DateOnly.fromDateTime(DateTime.parse('2024-10-01 00:00:00')) + ..heightInMetres = 1.7 + ..startWorkTime = TimeOnly.fromDateTimeString('06:00') + ..active = true + ..numbers = [2, 3, 5] + ..additionalData = {'a': 'some value', 'b': 12, 'c': false}; + final writer = JsonSerializationWriter() ..writeObjectValue( - null, simpleUser,); + null, + simpleUser, + ); expect( utf8.decode(writer.getSerializedContent()), - equals('{"id":"abc","createdDateTime":"2023-12-01T15:15:00.000","officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":1.7,"startWorkTime":"06:00:00","active":true,"numbers":[2,3,5],"a":"some value","b":12,"c":false}'), + equals( + '{"id":"abc","createdDateTime":"2023-12-01T15:15:00.000","officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":1.7,"startWorkTime":"06:00:00","active":true,"numbers":[2,3,5],"a":"some value","b":12,"c":false}'), ); }); - test('writeSecondObject', () { - final user1 = MicrosoftGraphUser() - ..officeLocation='on a chair' - ..workDuration=const Duration(hours: 2) - ..additionalData={'a':'#1 coworker'}; - final user2 = MicrosoftGraphUser() - ..workDuration=const Duration(hours: 12) - ..active=true; - final user3 = MicrosoftGraphUser() - ..heightInMetres=1.9 - ..endWorkTime=TimeOnly.fromDateTimeString('17:00'); - final group = MicrosoftGraphGroup() - ..name='a group' - ..leader=user3 - ..members=[user1,user2]; - + test('writeSecondObject', () { + final user1 = MicrosoftGraphUser() + ..officeLocation = 'on a chair' + ..workDuration = const Duration(hours: 2) + ..additionalData = {'a': '#1 coworker'}; + final user2 = MicrosoftGraphUser() + ..workDuration = const Duration(hours: 12) + ..active = true; + final user3 = MicrosoftGraphUser() + ..heightInMetres = 1.9 + ..endWorkTime = TimeOnly.fromDateTimeString('17:00'); + final group = MicrosoftGraphGroup() + ..name = 'a group' + ..leader = user3 + ..members = [user1, user2]; + final writer = JsonSerializationWriter() ..writeObjectValue( - null, group,); + null, + group, + ); expect( utf8.decode(writer.getSerializedContent()), - equals('{"name":"a group","leader":{"heightInMetres":1.9,"endWorkTime":"17:00:00"},"members":[{"officeLocation":"on a chair","workDuration":"2:00:00.000000","a":"#1 coworker"},{"workDuration":"12:00:00.000000","active":true}]}'), + equals( + '{"name":"a group","leader":{"heightInMetres":1.9,"endWorkTime":"17:00:00"},"members":[{"officeLocation":"on a chair","workDuration":"2:00:00.000000","a":"#1 coworker"},{"workDuration":"12:00:00.000000","active":true}]}'), ); }); }); diff --git a/packages/kiota_serialization_json/test/microsoft_graph_group.dart b/packages/kiota_serialization_json/test/microsoft_graph_group.dart index f5876a2..c27f6c8 100644 --- a/packages/kiota_serialization_json/test/microsoft_graph_group.dart +++ b/packages/kiota_serialization_json/test/microsoft_graph_group.dart @@ -26,10 +26,11 @@ class MicrosoftGraphGroup extends Parsable implements AdditionalDataHolder { Map getFieldDeserializers() { return { 'id': (node) => id = node.getStringValue(), - 'name': (node) => - name = node.getStringValue(), - 'leader': (node) => leader = node.getObjectValue(MicrosoftGraphUser.createFromDiscriminator), - 'members': (node) => members = node.getCollectionOfObjectValues(MicrosoftGraphUser.createFromDiscriminator), + 'name': (node) => name = node.getStringValue(), + 'leader': (node) => leader = + node.getObjectValue(MicrosoftGraphUser.createFromDiscriminator), + 'members': (node) => members = node.getCollectionOfObjectValues( + MicrosoftGraphUser.createFromDiscriminator), }; } diff --git a/packages/kiota_serialization_json/test/microsoft_graph_user.dart b/packages/kiota_serialization_json/test/microsoft_graph_user.dart index a05712e..133d09e 100644 --- a/packages/kiota_serialization_json/test/microsoft_graph_user.dart +++ b/packages/kiota_serialization_json/test/microsoft_graph_user.dart @@ -37,14 +37,17 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { String? officeLocation; bool? active; bool? accountEnabled; - Iterable numbers=[]; + Iterable numbers = []; @override void serialize(SerializationWriter writer) { writer ..writeStringValue('id', id) ..writeEnumValue( - 'namingEnum', namingEnum, _namingEnumSerializer,) + 'namingEnum', + namingEnum, + _namingEnumSerializer, + ) ..writeDateTimeValue('createdDateTime', createdDateTime) ..writeStringValue('officeLocation', officeLocation) ..writeDurationValue('workDuration', workDuration) @@ -52,8 +55,8 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { ..writeDoubleValue('heightInMetres', heightInMetres) ..writeTimeOnlyValue('startWorkTime', startWorkTime) ..writeTimeOnlyValue('endWorkTime', endWorkTime) - ..writeBoolValue('active', value:active) - ..writeBoolValue('accountEnabled', value:accountEnabled) + ..writeBoolValue('active', value: active) + ..writeBoolValue('accountEnabled', value: accountEnabled) ..writeCollectionOfPrimitiveValues('numbers', numbers) ..writeAdditionalData(additionalData); } @@ -73,7 +76,7 @@ class MicrosoftGraphUser extends Parsable implements AdditionalDataHolder { 'endWorkTime': (node) => endWorkTime = node.getTimeOnlyValue(), 'active': (node) => active = node.getBoolValue(), 'accountEnabled': (node) => accountEnabled = node.getBoolValue(), - 'numbers' : (node) => numbers = node.getCollectionOfPrimitiveValues(), + 'numbers': (node) => numbers = node.getCollectionOfPrimitiveValues(), }; } diff --git a/packages/kiota_serialization_json/test/second_test_entity.dart b/packages/kiota_serialization_json/test/second_test_entity.dart index f366f44..de37066 100644 --- a/packages/kiota_serialization_json/test/second_test_entity.dart +++ b/packages/kiota_serialization_json/test/second_test_entity.dart @@ -1,11 +1,10 @@ import 'package:kiota_abstractions/kiota_abstractions.dart'; class SecondTestEntity extends Parsable implements AdditionalDataHolder { - SecondTestEntity(); factory SecondTestEntity.createFromDiscriminatorValue(ParseNode parseNode) { - return SecondTestEntity(); + return SecondTestEntity(); } @override @@ -16,19 +15,19 @@ class SecondTestEntity extends Parsable implements AdditionalDataHolder { @override Map getFieldDeserializers() { - return { + return { 'id': (node) => id = node.getIntValue(), - 'displayName': (node) => - displayName = node.getStringValue(), + 'displayName': (node) => displayName = node.getStringValue(), 'failureRate': (node) => failureRate = node.getIntValue(), }; } - + @override void serialize(SerializationWriter writer) { - writer..writeStringValue("displayName", displayName) - ..writeIntValue("id", id) - ..writeIntValue("failureRate", failureRate) - ..writeAdditionalData(additionalData); + writer + ..writeStringValue("displayName", displayName) + ..writeIntValue("id", id) + ..writeIntValue("failureRate", failureRate) + ..writeAdditionalData(additionalData); } } diff --git a/packages/kiota_serialization_json/test/union_type_test.dart b/packages/kiota_serialization_json/test/union_type_test.dart index 0885a3a..927d314 100644 --- a/packages/kiota_serialization_json/test/union_type_test.dart +++ b/packages/kiota_serialization_json/test/union_type_test.dart @@ -15,8 +15,8 @@ void main() { final rawResponse = utf8.encode(initialString); final parseNode = JsonParseNodeFactory() .getRootParseNode('application/json', rawResponse); - final result = parseNode - .getObjectValue(UnionTypeMock.createFromDiscriminatorValue); + final result = + parseNode.getObjectValue(UnionTypeMock.createFromDiscriminatorValue); expect(result, isNotNull); if (result != null) { expect(result.composedType1, isNotNull); @@ -34,8 +34,8 @@ void main() { final rawResponse = utf8.encode(initialString); final parseNode = JsonParseNodeFactory() .getRootParseNode('application/json', rawResponse); - final result = parseNode - .getObjectValue(UnionTypeMock.createFromDiscriminatorValue); + final result = + parseNode.getObjectValue(UnionTypeMock.createFromDiscriminatorValue); expect(result, isNotNull); if (result != null) { expect(result.composedType1, isNull); @@ -51,8 +51,8 @@ void main() { final rawResponse = utf8.encode(initialString); final parseNode = JsonParseNodeFactory() .getRootParseNode('application/json', rawResponse); - final result = parseNode - .getObjectValue(UnionTypeMock.createFromDiscriminatorValue); + final result = + parseNode.getObjectValue(UnionTypeMock.createFromDiscriminatorValue); expect(result, isNotNull); if (result != null) { expect(result.composedType1, isNull); @@ -68,8 +68,8 @@ void main() { final rawResponse = utf8.encode(initialString); final parseNode = JsonParseNodeFactory() .getRootParseNode('application/json', rawResponse); - final result = parseNode - .getObjectValue(UnionTypeMock.createFromDiscriminatorValue); + final result = + parseNode.getObjectValue(UnionTypeMock.createFromDiscriminatorValue); expect(result, isNotNull); if (result != null) { expect(result.composedType1, isNull); @@ -88,12 +88,14 @@ void main() { expect(result, '"officeLocation"'); }); test('SerializeUnionTypeComplexProperty1', () { - final testEntity1 = MicrosoftGraphUser()..officeLocation='Montreal'..id='opaque'; - final testEntity2 = SecondTestEntity()..displayName='McGill'; + final testEntity1 = MicrosoftGraphUser() + ..officeLocation = 'Montreal' + ..id = 'opaque'; + final testEntity2 = SecondTestEntity()..displayName = 'McGill'; final writer = JsonSerializationWriter(); UnionTypeMock() - ..composedType1=testEntity1 - ..composedType2=testEntity2 + ..composedType1 = testEntity1 + ..composedType2 = testEntity2 ..serialize(writer); final content = writer.getSerializedContent(); final result = utf8.decode(content); @@ -101,25 +103,32 @@ void main() { }); test('SerializeUnionTypeComplexProperty2', () { - final testEntity2 = SecondTestEntity()..displayName='McGill'..id=10; + final testEntity2 = SecondTestEntity() + ..displayName = 'McGill' + ..id = 10; final writer = JsonSerializationWriter(); UnionTypeMock() - ..composedType2=testEntity2 + ..composedType2 = testEntity2 ..serialize(writer); final content = writer.getSerializedContent(); final result = utf8.decode(content); expect(result, '{"displayName":"McGill","id":10}'); }); test('SerializeUnionComplexProperty3', () { - final testEntity1 = MicrosoftGraphUser()..officeLocation='Montreal'..id='10'; - final testEntity2 = MicrosoftGraphUser()..officeLocation='Ottawa'..id='11'; + final testEntity1 = MicrosoftGraphUser() + ..officeLocation = 'Montreal' + ..id = '10'; + final testEntity2 = MicrosoftGraphUser() + ..officeLocation = 'Ottawa' + ..id = '11'; final writer = JsonSerializationWriter(); UnionTypeMock() - ..composedType3=[testEntity1, testEntity2] + ..composedType3 = [testEntity1, testEntity2] ..serialize(writer); final content = writer.getSerializedContent(); final result = utf8.decode(content); - expect(result, '[{"id":"10","officeLocation":"Montreal"},{"id":"11","officeLocation":"Ottawa"}]'); + expect(result, + '[{"id":"10","officeLocation":"Montreal"},{"id":"11","officeLocation":"Ottawa"}]'); }); }); } diff --git a/packages/kiota_serialization_json/test/untyped_test_entity.dart b/packages/kiota_serialization_json/test/untyped_test_entity.dart index 2b4a1f2..2ff4be6 100644 --- a/packages/kiota_serialization_json/test/untyped_test_entity.dart +++ b/packages/kiota_serialization_json/test/untyped_test_entity.dart @@ -4,11 +4,9 @@ class UntypedTestEntity extends Parsable implements AdditionalDataHolder { UntypedTestEntity(); factory UntypedTestEntity.createFromDiscriminator(ParseNode parseNode) { - final discriminatorValue = parseNode.getChildNode('@odata.type')?.getStringValue(); - return switch(discriminatorValue) - { - _ => UntypedTestEntity() - }; + final discriminatorValue = + parseNode.getChildNode('@odata.type')?.getStringValue(); + return switch (discriminatorValue) { _ => UntypedTestEntity() }; } /// Stores additional data not described in the OpenAPI description @@ -26,13 +24,17 @@ class UntypedTestEntity extends Parsable implements AdditionalDataHolder { @override Map getFieldDeserializers() { - return { + return { 'id': (node) => id = node.getStringValue(), 'title': (node) => title = node.getStringValue(), - 'location': (node) => location = node.getObjectValue(UntypedNode.createFromDiscriminatorValue), - 'keywords': (node) => keywords = node.getObjectValue(UntypedNode.createFromDiscriminatorValue), - 'detail': (node) => detail = node.getObjectValue(UntypedNode.createFromDiscriminatorValue), - 'table': (node) => table = node.getObjectValue(UntypedNode.createFromDiscriminatorValue), + 'location': (node) => location = + node.getObjectValue(UntypedNode.createFromDiscriminatorValue), + 'keywords': (node) => keywords = + node.getObjectValue(UntypedNode.createFromDiscriminatorValue), + 'detail': (node) => detail = + node.getObjectValue(UntypedNode.createFromDiscriminatorValue), + 'table': (node) => + table = node.getObjectValue(UntypedNode.createFromDiscriminatorValue), }; } @@ -47,5 +49,4 @@ class UntypedTestEntity extends Parsable implements AdditionalDataHolder { ..writeObjectValue('table', table) ..writeAdditionalData(additionalData); } - } From 9c38dd5d5f888c3217254e9c66d4bf5542785224 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Fri, 18 Oct 2024 14:38:39 +0200 Subject: [PATCH 51/69] Remove settings file --- .vscode/settings.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 082b194..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "makefile.configureOnOpen": false -} \ No newline at end of file From b14f1707192b04b66a676ff32e74d6e5e1f5f61d Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Wed, 23 Oct 2024 07:25:48 +0200 Subject: [PATCH 52/69] Initial commit Current status is that seriaization fails on null value for additional data. --- .../CHANGELOG.md | 4 + .../kiota_serialization_multipart/README.md | 21 +++ .../analysis_options.yaml | 1 + .../lib/kiota_serialization_multipart.dart | 14 ++ .../src/multipart_serialization_writer.dart | 137 ++++++++++++++++++ ...ultipart_serialization_writer_factory.dart | 17 +++ .../pubspec.yaml | 23 +++ .../multipart_serialization_writer_test.dart | 77 ++++++++++ .../test/test_entity.dart | 56 +++++++ 9 files changed, 350 insertions(+) create mode 100644 packages/kiota_serialization_multipart/CHANGELOG.md create mode 100644 packages/kiota_serialization_multipart/README.md create mode 100644 packages/kiota_serialization_multipart/analysis_options.yaml create mode 100644 packages/kiota_serialization_multipart/lib/kiota_serialization_multipart.dart create mode 100644 packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart create mode 100644 packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer_factory.dart create mode 100644 packages/kiota_serialization_multipart/pubspec.yaml create mode 100644 packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart create mode 100644 packages/kiota_serialization_multipart/test/test_entity.dart diff --git a/packages/kiota_serialization_multipart/CHANGELOG.md b/packages/kiota_serialization_multipart/CHANGELOG.md new file mode 100644 index 0000000..fcb0bc7 --- /dev/null +++ b/packages/kiota_serialization_multipart/CHANGELOG.md @@ -0,0 +1,4 @@ +# Unreleased + +- Initial version. +- Provides parsing and serialization support for the `multipart/form-data` content type. diff --git a/packages/kiota_serialization_multipart/README.md b/packages/kiota_serialization_multipart/README.md new file mode 100644 index 0000000..aeed8da --- /dev/null +++ b/packages/kiota_serialization_multipart/README.md @@ -0,0 +1,21 @@ +The `kiota_serialization_multipart` package is the Dart Json serialization library implementation to +handle `multipart/form-data` responses. + +## Usage + +Install the package in the generated project: + +> For now, you can add the git repository as a dependency in your `pubspec.yaml` file: +> +> ```yaml +> dependencies: +> kiota_serialization_multipart: +> git: +> url: https://github.com/kiota-community/dart_kiota.git +> ref: main +> path: packages/kiota_serialization_multipart +> ``` + +```bash +dart pub add kiota_serialization_multipart +``` diff --git a/packages/kiota_serialization_multipart/analysis_options.yaml b/packages/kiota_serialization_multipart/analysis_options.yaml new file mode 100644 index 0000000..feb86ff --- /dev/null +++ b/packages/kiota_serialization_multipart/analysis_options.yaml @@ -0,0 +1 @@ +include: package:strict/analysis_options.yaml diff --git a/packages/kiota_serialization_multipart/lib/kiota_serialization_multipart.dart b/packages/kiota_serialization_multipart/lib/kiota_serialization_multipart.dart new file mode 100644 index 0000000..34732b5 --- /dev/null +++ b/packages/kiota_serialization_multipart/lib/kiota_serialization_multipart.dart @@ -0,0 +1,14 @@ +/// This library implements deserialization for text/plain responses. +/// +/// This library is not meant to be used directly, but rather to be used as a +/// dependency in the generated code. +library kiota_serialization_text; + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:kiota_abstractions/kiota_abstractions.dart'; +import 'package:uuid/uuid_value.dart'; + +part 'src/multipart_serialization_writer.dart'; +part 'src/multipart_serialization_writer_factory.dart'; diff --git a/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart b/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart new file mode 100644 index 0000000..d740534 --- /dev/null +++ b/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart @@ -0,0 +1,137 @@ +part of '../kiota_serialization_multipart.dart'; + +class MultipartSerializationWriter implements SerializationWriter { + final StringBuffer _buffer = StringBuffer(); + final errorMessagePrefix = 'Multipart serialization does not support writing'; + + @override + ParsableHook? onAfterObjectSerialization; + + @override + ParsableHook? onBeforeObjectSerialization; + + @override + void Function(Parsable p1, SerializationWriter p2)? + onStartObjectSerialization; + + @override + Uint8List getSerializedContent() { + return utf8.encode(_buffer.toString()); + } + + @override + void writeAdditionalData(Map value) { + throw UnsupportedError('$errorMessagePrefix additional data'); + } + + @override + void writeBoolValue(String? key, {bool? value}) { + throw UnsupportedError('$errorMessagePrefix boolean values'); + } + + @override + void writeByteArrayValue(String? key, Uint8List? value) { + if (value != null) { + _buffer.write(value); + } + } + + @override + void writeCollectionOfEnumValues( + String? key, Iterable? values, EnumSerializer serializer,) { + throw UnsupportedError('$errorMessagePrefix collection of enum values'); + } + + @override + void writeCollectionOfObjectValues( + String? key, Iterable? values,) { + throw UnsupportedError('$errorMessagePrefix collection of object values'); + } + + @override + void writeCollectionOfPrimitiveValues(String? key, Iterable? values) { + throw UnsupportedError('$errorMessagePrefix collection of primitive values'); + } + + @override + void writeDateOnlyValue(String? key, DateOnly? value) { + throw UnsupportedError('$errorMessagePrefix date values'); + } + + @override + void writeDateTimeValue(String? key, DateTime? value) { + throw UnsupportedError('$errorMessagePrefix date/time values'); + } + + @override + void writeDoubleValue(String? key, double? value) { + throw UnsupportedError('$errorMessagePrefix double values'); + } + + @override + void writeDurationValue(String? key, Duration? value) { + throw UnsupportedError('$errorMessagePrefix durations'); + } + + @override + void writeEnumValue( + String? key, T? value, EnumSerializer serializer,) { + throw UnsupportedError('$errorMessagePrefix enum values'); + } + + @override + void writeIntValue(String? key, int? value) { + throw UnsupportedError('$errorMessagePrefix int values'); + } + + @override + void writeNullValue(String? key) { + throw UnsupportedError('$errorMessagePrefix null values'); + } + + @override + void writeObjectValue(String? key, T? value, + [Iterable? additionalValuesToMerge,]) { + if (value != null) { + if (onBeforeObjectSerialization != null) { + onBeforeObjectSerialization?.call(value); + } + if (value is MultipartBody) { + if (onStartObjectSerialization != null) { + onStartObjectSerialization?.call(value, this); + } + value.serialize(this); + } else { + throw Exception('Expected MultipartBody instance but got ${value.runtimeType}'); + } + if (onAfterObjectSerialization != null) { + onAfterObjectSerialization?.call(value); + } + } + + } + + @override + void writeStringValue(String? key, String? value) { + if (key != null && key.isNotEmpty) { + _buffer.write(key); + } + if (value != null && value.isNotEmpty) { + if (key != null && key.isNotEmpty) { + _buffer.write(': '); + } + _buffer.write(value); + } + _buffer.write('\r\n'); + } + + @override + void writeTimeOnlyValue(String? key, TimeOnly? value) { + throw UnsupportedError('$errorMessagePrefix time values'); + } + + @override + void writeUuidValue(String? key, UuidValue? value) { + throw UnsupportedError('$errorMessagePrefix Uuids'); + } +} diff --git a/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer_factory.dart b/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer_factory.dart new file mode 100644 index 0000000..dc3184d --- /dev/null +++ b/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer_factory.dart @@ -0,0 +1,17 @@ +part of '../kiota_serialization_multipart.dart'; + +class MultipartSerializationWriterFactory implements SerializationWriterFactory { + @override + SerializationWriter getSerializationWriter(String contentType) { + if (contentType.toLowerCase() != validContentType) { + throw ArgumentError( + 'The provided content type is not supported by the MultipartSerializationWriterFactory', + ); + } + + return MultipartSerializationWriter(); + } + + @override + String get validContentType => 'multipart/form-data'; +} diff --git a/packages/kiota_serialization_multipart/pubspec.yaml b/packages/kiota_serialization_multipart/pubspec.yaml new file mode 100644 index 0000000..7de5a6f --- /dev/null +++ b/packages/kiota_serialization_multipart/pubspec.yaml @@ -0,0 +1,23 @@ +name: kiota_serialization_multipart +description: "Provides parsing and serialization support for the `multipart/form-data` content type." +version: 0.0.1-pre.1 +homepage: https://github.com/kiota-community/dart_kiota/tree/main/packages/kiota_serialization_multipart +repository: https://github.com/kiota-community/dart_kiota +publish_to: 'none' + +environment: + sdk: '>=3.2.6 <4.0.0' + +dependencies: + http: ^1.2.2 + kiota_abstractions: + path: ../kiota_abstractions + uuid: ^4.4.2 + +dev_dependencies: + build_runner: ^2.4.9 + kiota_serialization_json: + path: ../kiota_serialization_json/ + mockito: ^5.4.4 + strict: ^2.0.0 + test: ^1.25.2 diff --git a/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart b/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart new file mode 100644 index 0000000..cdcd412 --- /dev/null +++ b/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart @@ -0,0 +1,77 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:kiota_abstractions/kiota_abstractions.dart'; +import 'package:kiota_serialization_json/kiota_serialization_json.dart'; +import 'package:kiota_serialization_multipart/kiota_serialization_multipart.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:test/test.dart'; + +import 'multipart_serialization_writer_test.mocks.dart'; +import 'test_entity.dart'; + +String? _httpMethodEnumSerializer(HttpMethod? value) => value?.name; + +@GenerateMocks([RequestAdapter]) +void main() { + group('MultipartSerializationWriter', () { + test('writeEnumValue wich is unsupported', () { + final writer = MultipartSerializationWriter(); + expect( + () => writer.writeEnumValue( + null, + HttpMethod.get, + _httpMethodEnumSerializer, + ), + throwsUnsupportedError, + ); + }); + test('writeStringValue', () { + var writer = MultipartSerializationWriter() + ..writeStringValue(null, 'value'); + + expect(writer.getSerializedContent(), utf8.encode('value\r\n')); + + writer = MultipartSerializationWriter()..writeStringValue('key', 'value'); + expect(writer.getSerializedContent(), utf8.encode('key: value\r\n')); + }); + + test('writeObjectValue', () { + final binaryData = Uint8List.fromList([0x01, 0x02, 0x03]); + + final requestAdapter = MockRequestAdapter(); + when(requestAdapter.serializationWriterFactory) + .thenReturn(JsonSerializationWriterFactory()); + + final testEntity = TestEntity() + ..id = '48e31887-5dad-4d73-a9f5-3c356e68a038' + ..birthDay = DateOnly.fromComponents(1961, 9, 29) + ..workDuration = const Duration(hours: 8) + ..startWorkTime = TimeOnly.fromComponents(6, 30) + ..endWorkTime = TimeOnly.fromComponents(15, 0) + ..deviceNames = ['device1', 'device2'] + ..additionalData = { + 'mobilePhone': null, + 'jobTitle': 'Author', + 'accountEnabled': false, + 'createdDateTime': DateTime(1961, 9, 29, 8, 31), + 'otherPhones': ['device1', 'device2'], + }; + + final multipartBody = MultipartBody() + ..requestAdapter = requestAdapter + ..addOrReplace('testEntity', 'application/json', testEntity) + ..addOrReplace('image', 'application/octet-stream', binaryData); + + final serializationWriter = MultipartSerializationWriter() + ..writeObjectValue(null, multipartBody); + final content = serializationWriter.getSerializedContent(); + final expected = ''' + ${multipartBody.boundary} + '''; + + expect(content, expected); + }); + }); +} diff --git a/packages/kiota_serialization_multipart/test/test_entity.dart b/packages/kiota_serialization_multipart/test/test_entity.dart new file mode 100644 index 0000000..86531d1 --- /dev/null +++ b/packages/kiota_serialization_multipart/test/test_entity.dart @@ -0,0 +1,56 @@ +import 'package:kiota_abstractions/kiota_abstractions.dart'; + +class TestEntity implements Parsable, AdditionalDataHolder { + TestEntity(); + + String? id; + + String? officeLocation; + + DateOnly? birthDay; + + Iterable? deviceNames = []; + + Duration? workDuration; + + TimeOnly? startWorkTime; + + TimeOnly? endWorkTime; + + DateTime? createdDateTime; + + @override + Map additionalData = {}; + + @override + Map getFieldDeserializers() { + return { + 'id': (node) => id = node.getStringValue(), + 'officeLocation': (node) => officeLocation = node.getStringValue(), + 'birthDay': (node) => birthDay = node.getDateOnlyValue(), + 'deviceNames': (node) => deviceNames = node.getCollectionOfPrimitiveValues(), + 'workDuration': (node) => workDuration = node.getDurationValue(), + 'startWorkTime': (node) => startWorkTime = node.getTimeOnlyValue(), + 'endWorkTime': (node) => endWorkTime = node.getTimeOnlyValue(), + 'createdDateTime': (node) => createdDateTime = node.getDateTimeValue() + }; + } + + @override + void serialize(SerializationWriter writer) { + writer + ..writeStringValue('id', id) + ..writeStringValue('officeLocation', officeLocation) + ..writeDateOnlyValue('birthDay', birthDay) + ..writeDurationValue('workDuration', workDuration) + ..writeTimeOnlyValue('startWorkTime', startWorkTime) + ..writeTimeOnlyValue('endWorkTime', endWorkTime) + ..writeDateTimeValue('createdDateTime', createdDateTime) + ..writeCollectionOfPrimitiveValues('deviceNames', deviceNames) + ..writeAdditionalData(additionalData); + } + + static TestEntity createFromDiscriminatorValue(ParseNode parseNode) { + return TestEntity(); + } +} From 54f68258030cfb2c001ce63e6269f548d82af552 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Wed, 23 Oct 2024 13:17:09 +0200 Subject: [PATCH 53/69] Fixed writing a null value for additonal data. --- .../lib/src/json_serialization_writer.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index a26a7f8..156c9bf 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -30,7 +30,11 @@ class JsonSerializationWriter implements SerializationWriter { if (entry.value is bool || entry.value is int || entry.value is double) { _buffer.add('"${entry.key}":${entry.value}'); } else { - _buffer.add('"${entry.key}":"${_getAnyValue(entry.value as Object)}"'); + if (entry.value == null) { + _buffer.add('"${entry.key}": null'); + } else { + _buffer.add('"${entry.key}":"${_getAnyValue(entry.value as Object)}"'); + } } _buffer.add(separator); } From 022bcc2ab33482ffa8ecc17dda0fefec24981563 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Wed, 23 Oct 2024 13:17:47 +0200 Subject: [PATCH 54/69] Multipart now has a working unit test. Switched from StringBuffer to using Uint8Buffer as it supports adding (binary) data. --- .../lib/kiota_serialization_multipart.dart | 1 + .../src/multipart_serialization_writer.dart | 43 ++++++++++++------- .../pubspec.yaml | 1 + .../multipart_serialization_writer_test.dart | 11 +++-- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/packages/kiota_serialization_multipart/lib/kiota_serialization_multipart.dart b/packages/kiota_serialization_multipart/lib/kiota_serialization_multipart.dart index 34732b5..f2c1035 100644 --- a/packages/kiota_serialization_multipart/lib/kiota_serialization_multipart.dart +++ b/packages/kiota_serialization_multipart/lib/kiota_serialization_multipart.dart @@ -8,6 +8,7 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:kiota_abstractions/kiota_abstractions.dart'; +import 'package:typed_data/typed_buffers.dart'; import 'package:uuid/uuid_value.dart'; part 'src/multipart_serialization_writer.dart'; diff --git a/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart b/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart index d740534..5d5cb7c 100644 --- a/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart +++ b/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart @@ -1,7 +1,8 @@ part of '../kiota_serialization_multipart.dart'; class MultipartSerializationWriter implements SerializationWriter { - final StringBuffer _buffer = StringBuffer(); + final Uint8Buffer _buffer = Uint8Buffer(); + final errorMessagePrefix = 'Multipart serialization does not support writing'; @override @@ -16,7 +17,7 @@ class MultipartSerializationWriter implements SerializationWriter { @override Uint8List getSerializedContent() { - return utf8.encode(_buffer.toString()); + return Uint8List.fromList(_buffer); } @override @@ -32,25 +33,31 @@ class MultipartSerializationWriter implements SerializationWriter { @override void writeByteArrayValue(String? key, Uint8List? value) { if (value != null) { - _buffer.write(value); + _buffer.addAll(value); } } @override void writeCollectionOfEnumValues( - String? key, Iterable? values, EnumSerializer serializer,) { + String? key, + Iterable? values, + EnumSerializer serializer, + ) { throw UnsupportedError('$errorMessagePrefix collection of enum values'); } @override void writeCollectionOfObjectValues( - String? key, Iterable? values,) { + String? key, + Iterable? values, + ) { throw UnsupportedError('$errorMessagePrefix collection of object values'); } @override void writeCollectionOfPrimitiveValues(String? key, Iterable? values) { - throw UnsupportedError('$errorMessagePrefix collection of primitive values'); + throw UnsupportedError( + '$errorMessagePrefix collection of primitive values'); } @override @@ -75,7 +82,10 @@ class MultipartSerializationWriter implements SerializationWriter { @override void writeEnumValue( - String? key, T? value, EnumSerializer serializer,) { + String? key, + T? value, + EnumSerializer serializer, + ) { throw UnsupportedError('$errorMessagePrefix enum values'); } @@ -90,8 +100,11 @@ class MultipartSerializationWriter implements SerializationWriter { } @override - void writeObjectValue(String? key, T? value, - [Iterable? additionalValuesToMerge,]) { + void writeObjectValue( + String? key, + T? value, [ + Iterable? additionalValuesToMerge, + ]) { if (value != null) { if (onBeforeObjectSerialization != null) { onBeforeObjectSerialization?.call(value); @@ -102,27 +115,27 @@ class MultipartSerializationWriter implements SerializationWriter { } value.serialize(this); } else { - throw Exception('Expected MultipartBody instance but got ${value.runtimeType}'); + throw Exception( + 'Expected MultipartBody instance but got ${value.runtimeType}'); } if (onAfterObjectSerialization != null) { onAfterObjectSerialization?.call(value); } } - } @override void writeStringValue(String? key, String? value) { if (key != null && key.isNotEmpty) { - _buffer.write(key); + _buffer.addAll(utf8.encode(key)); } if (value != null && value.isNotEmpty) { if (key != null && key.isNotEmpty) { - _buffer.write(': '); + _buffer.addAll(utf8.encode(': ')); } - _buffer.write(value); + _buffer.addAll(utf8.encode(value)); } - _buffer.write('\r\n'); + _buffer.addAll(utf8.encode('\r\n')); } @override diff --git a/packages/kiota_serialization_multipart/pubspec.yaml b/packages/kiota_serialization_multipart/pubspec.yaml index 7de5a6f..25dde08 100644 --- a/packages/kiota_serialization_multipart/pubspec.yaml +++ b/packages/kiota_serialization_multipart/pubspec.yaml @@ -12,6 +12,7 @@ dependencies: http: ^1.2.2 kiota_abstractions: path: ../kiota_abstractions + typed_data: ^1.3.2 uuid: ^4.4.2 dev_dependencies: diff --git a/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart b/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart index cdcd412..b06ea52 100644 --- a/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart +++ b/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart @@ -66,12 +66,15 @@ void main() { final serializationWriter = MultipartSerializationWriter() ..writeObjectValue(null, multipartBody); - final content = serializationWriter.getSerializedContent(); + final stringContent = + String.fromCharCodes(serializationWriter.getSerializedContent()); + final expected = ''' - ${multipartBody.boundary} - '''; +--${multipartBody.boundary}\r +Content-Type: application/json\r +Content-Disposition: form-data; name="testEntity"'''; - expect(content, expected); + expect(stringContent.substring(0, expected.length), expected); }); }); } From 95105372ab3ea85ba627d4b70a557605a2496c26 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Wed, 23 Oct 2024 14:13:08 +0200 Subject: [PATCH 55/69] Made all untyped_... constructors const In the process I had to make the return value of getValue(), nullable. --- .../lib/src/serialization/untyped_array.dart | 5 ++--- .../lib/src/serialization/untyped_boolean.dart | 2 +- .../lib/src/serialization/untyped_double.dart | 2 +- .../lib/src/serialization/untyped_integer.dart | 2 +- .../lib/src/serialization/untyped_node.dart | 11 +++++------ .../lib/src/serialization/untyped_null.dart | 7 +++++-- .../lib/src/serialization/untyped_object.dart | 4 ++-- .../lib/src/serialization/untyped_string.dart | 2 +- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_array.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_array.dart index 89641fe..31455e2 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_array.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_array.dart @@ -2,11 +2,10 @@ part of '../../kiota_abstractions.dart'; /// Represents an untyped node with a collection of other untyped nodes. class UntypedArray extends UntypedNode { - /// Constructs an instance from the supplied [collection] - UntypedArray(this.collection); + const UntypedArray(this.collection); - Iterable collection; + final Iterable collection; @override Iterable getValue() { diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_boolean.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_boolean.dart index 37de008..9e08e54 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_boolean.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_boolean.dart @@ -1,7 +1,7 @@ part of '../../kiota_abstractions.dart'; class UntypedBoolean extends UntypedNode { - UntypedBoolean({required this.value}); + const UntypedBoolean({required this.value}); final bool value; } diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_double.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_double.dart index 1a26fe9..e7dfc74 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_double.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_double.dart @@ -1,7 +1,7 @@ part of '../../kiota_abstractions.dart'; class UntypedDouble extends UntypedNode { - UntypedDouble(this.value); + const UntypedDouble(this.value); final double value; } diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_integer.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_integer.dart index 3d32fd7..5d431ef 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_integer.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_integer.dart @@ -1,7 +1,7 @@ part of '../../kiota_abstractions.dart'; class UntypedInteger extends UntypedNode { - UntypedInteger(this.value); + const UntypedInteger(this.value); final int value; } diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart index 0fee423..491f347 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart @@ -2,12 +2,11 @@ part of '../../kiota_abstractions.dart'; /// Base class for untyped node. class UntypedNode implements Parsable { - UntypedNode(); + const UntypedNode(); - /// Creates a new [UntypedNode] instance of the appropriate class - /// based on discriminator value. - factory UntypedNode.createFromDiscriminatorValue(ParseNode parseNode) { - return UntypedNode(); + /// Creates a new [UntypedNode] instance. + factory UntypedNode.createFromDiscriminatorValue(ParseNode _) { + return const UntypedNode(); } /// The deserialization information for the current model. /// Returns a map of serializer methods for this object. @@ -23,7 +22,7 @@ class UntypedNode implements Parsable { } /// Gets the value assigned to untyped node. - Object getValue() { + Object? getValue() { throw Exception('getValue is implemented for derived types of UntypedNode'); } } diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_null.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_null.dart index 44249bf..add3a4e 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_null.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_null.dart @@ -1,7 +1,10 @@ part of '../../kiota_abstractions.dart'; class UntypedNull extends UntypedNode { - UntypedNull(); + const UntypedNull(); - final dynamic value = null; + @override + Object? getValue() { + return null; + } } diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_object.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_object.dart index b539295..d4a756b 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_object.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_object.dart @@ -2,7 +2,7 @@ part of '../../kiota_abstractions.dart'; /// Represents an untyped node with object value. class UntypedObject extends UntypedNode { - UntypedObject(this.properties); + const UntypedObject(this.properties); - Map properties; + final Map properties; } diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart index 149e037..f8f6813 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart @@ -2,7 +2,7 @@ part of '../../kiota_abstractions.dart'; class UntypedString extends UntypedNode { - UntypedString(this.value); + const UntypedString(this.value); final String value; } From b0be35976628e9ef6195ed3a3eff98ecfd8efd29 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Thu, 24 Oct 2024 15:34:30 +0200 Subject: [PATCH 56/69] Temporary fix to have a hard coded version number I know that the version.dart file is generated and not committed, but if I want to hand a generated SDK to a client they do not have the generated file and run into a problem. I will have to discuss this with Ricardo. --- packages/kiota_http/lib/src/kiota_client_factory.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kiota_http/lib/src/kiota_client_factory.dart b/packages/kiota_http/lib/src/kiota_client_factory.dart index 04b5776..e0c8583 100644 --- a/packages/kiota_http/lib/src/kiota_client_factory.dart +++ b/packages/kiota_http/lib/src/kiota_client_factory.dart @@ -20,7 +20,7 @@ class KiotaClientFactory { return retryCodes.contains(response.statusCode); }, ), - userAgent: 'kiota_http/$packageVersion', + userAgent: 'kiota_http/0.0.1', ); } } From 51bead9fac634d2aed7c450f18534fc82c7f4278 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Thu, 24 Oct 2024 15:34:30 +0200 Subject: [PATCH 57/69] Temporary fix to have a hard coded version number I know that the version.dart file is generated and not committed, but if I want to hand a generated SDK to a client they do not have the generated file and run into a problem. I will have to discuss this with Ricardo. --- packages/kiota_http/lib/kiota_http.dart | 1 - packages/kiota_http/lib/src/kiota_client_factory.dart | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/kiota_http/lib/kiota_http.dart b/packages/kiota_http/lib/kiota_http.dart index fd8bd9a..ad237ec 100644 --- a/packages/kiota_http/lib/kiota_http.dart +++ b/packages/kiota_http/lib/kiota_http.dart @@ -7,7 +7,6 @@ import 'dart:typed_data'; import 'package:http/http.dart' as http; import 'package:http/retry.dart' as retry; import 'package:kiota_abstractions/kiota_abstractions.dart'; -import 'package:kiota_http/gen/version.dart'; import 'package:uuid/uuid.dart'; part 'src/http_client_request_adapter.dart'; diff --git a/packages/kiota_http/lib/src/kiota_client_factory.dart b/packages/kiota_http/lib/src/kiota_client_factory.dart index 04b5776..e0c8583 100644 --- a/packages/kiota_http/lib/src/kiota_client_factory.dart +++ b/packages/kiota_http/lib/src/kiota_client_factory.dart @@ -20,7 +20,7 @@ class KiotaClientFactory { return retryCodes.contains(response.statusCode); }, ), - userAgent: 'kiota_http/$packageVersion', + userAgent: 'kiota_http/0.0.1', ); } } From 5270a7cefe3e63f69b658d4c54d844115d2e00de Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Mon, 28 Oct 2024 11:29:49 +0100 Subject: [PATCH 58/69] Resolved compiler warings and formatted the code. --- .../lib/src/case_insensitive_map.dart | 4 +- .../request_information_extensions.dart | 5 ++- .../lib/src/serialization/untyped_node.dart | 41 ++++++++++--------- .../lib/src/serialization/untyped_string.dart | 1 - .../parse_node_factory_registry_test.dart | 11 +++-- ...lization_writer_factory_registry_test.dart | 11 +++-- .../lib/src/form_serialization_writer.dart | 2 +- .../test/form_parse_node_test.dart | 2 +- .../lib/src/json_parse_node.dart | 2 +- .../test/intersection_type_test.dart | 12 ++++-- .../test/json_parse_node_factory_test.dart | 10 +++-- .../test/json_parse_node_test.dart | 6 ++- ...son_serialization_writer_factory_test.dart | 8 ++-- .../test/json_serialization_writer_test.dart | 6 ++- .../test/microsoft_graph_group.dart | 3 +- .../test/second_test_entity.dart | 8 ++-- .../test/union_type_mock.dart | 6 ++- .../test/union_type_test.dart | 6 ++- .../test/text_parse_node_test.dart | 2 +- 19 files changed, 85 insertions(+), 61 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/case_insensitive_map.dart b/packages/kiota_abstractions/lib/src/case_insensitive_map.dart index a55fa69..35b42ce 100644 --- a/packages/kiota_abstractions/lib/src/case_insensitive_map.dart +++ b/packages/kiota_abstractions/lib/src/case_insensitive_map.dart @@ -112,9 +112,9 @@ class CaseInsensitiveMap implements Map { final normalizedKey = normalizeKey(key); return _contents.putIfAbsent(normalizedKey, () { - _originalKeys[normalizedKey] = key; + _originalKeys[normalizedKey] = key; - return ifAbsent(); + return ifAbsent(); }); } diff --git a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart index 4e02dff..615404a 100644 --- a/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart +++ b/packages/kiota_abstractions/lib/src/extensions/request_information_extensions.dart @@ -138,8 +138,9 @@ extension RequestInformationExtensions on RequestInformation { } void configure( - void Function(RequestConfiguration)? configurator, - T Function()? createParameters) { + void Function(RequestConfiguration)? configurator, + T Function()? createParameters, + ) { if (configurator == null || createParameters == null) { return; } diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart index 491f347..8c0a0f0 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_node.dart @@ -2,27 +2,28 @@ part of '../../kiota_abstractions.dart'; /// Base class for untyped node. class UntypedNode implements Parsable { - const UntypedNode(); + const UntypedNode(); - /// Creates a new [UntypedNode] instance. - factory UntypedNode.createFromDiscriminatorValue(ParseNode _) { - return const UntypedNode(); - } - /// The deserialization information for the current model. - /// Returns a map of serializer methods for this object. - @override - Map getFieldDeserializers() { - return {}; - } + /// Creates a new [UntypedNode] instance. + factory UntypedNode.createFromDiscriminatorValue(ParseNode _) { + return const UntypedNode(); + } - /// Serializes the current object - @override - void serialize(SerializationWriter writer) { - // no properties to serialize. This is handled by custom serialization logic. - } + /// The deserialization information for the current model. + /// Returns a map of serializer methods for this object. + @override + Map getFieldDeserializers() { + return {}; + } - /// Gets the value assigned to untyped node. - Object? getValue() { - throw Exception('getValue is implemented for derived types of UntypedNode'); - } + /// Serializes the current object + @override + void serialize(SerializationWriter writer) { + // no properties to serialize. This is handled by custom serialization logic. + } + + /// Gets the value assigned to untyped node. + Object? getValue() { + throw Exception('getValue is implemented for derived types of UntypedNode'); + } } diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart index f8f6813..4dfa6b8 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart @@ -1,7 +1,6 @@ part of '../../kiota_abstractions.dart'; class UntypedString extends UntypedNode { - const UntypedString(this.value); final String value; diff --git a/packages/kiota_abstractions/test/serialization/parse_node_factory_registry_test.dart b/packages/kiota_abstractions/test/serialization/parse_node_factory_registry_test.dart index 5f5b27b..22a1b13 100644 --- a/packages/kiota_abstractions/test/serialization/parse_node_factory_registry_test.dart +++ b/packages/kiota_abstractions/test/serialization/parse_node_factory_registry_test.dart @@ -12,11 +12,14 @@ void main() { test('VendorSpecificContentType', () { const contentType = 'application/json'; final mockFactory = MockParseNodeFactory(); - final jsonStream= utf8.encode('{"test": "input"}'); + final jsonStream = utf8.encode('{"test": "input"}'); final mockParseNode = MockParseNode(); - when(mockFactory.getRootParseNode(contentType, jsonStream)).thenReturn(mockParseNode); - ParseNodeFactoryRegistry.defaultInstance.contentTypeAssociatedFactories.putIfAbsent(contentType, ()=>mockFactory); - final rootParseNode = ParseNodeFactoryRegistry.defaultInstance.getRootParseNode('application/vnd+json', jsonStream); + when(mockFactory.getRootParseNode(contentType, jsonStream)) + .thenReturn(mockParseNode); + ParseNodeFactoryRegistry.defaultInstance.contentTypeAssociatedFactories + .putIfAbsent(contentType, () => mockFactory); + final rootParseNode = ParseNodeFactoryRegistry.defaultInstance + .getRootParseNode('application/vnd+json', jsonStream); expect(rootParseNode, isNotNull); }); }); diff --git a/packages/kiota_abstractions/test/serialization/serialization_writer_factory_registry_test.dart b/packages/kiota_abstractions/test/serialization/serialization_writer_factory_registry_test.dart index cebde1e..64590f2 100644 --- a/packages/kiota_abstractions/test/serialization/serialization_writer_factory_registry_test.dart +++ b/packages/kiota_abstractions/test/serialization/serialization_writer_factory_registry_test.dart @@ -11,9 +11,14 @@ void main() { const contentType = 'application/text'; final mockWriter = MockSerializationWriter(); final mockFactory = MockSerializationWriterFactory(); - when(mockFactory.getSerializationWriter(contentType)).thenReturn(mockWriter); - SerializationWriterFactoryRegistry.defaultInstance.contentTypeAssociatedFactories.putIfAbsent(contentType, () => mockFactory); - final serializationWriter = SerializationWriterFactoryRegistry.defaultInstance.getSerializationWriter('application/vnd+text'); + when(mockFactory.getSerializationWriter(contentType)) + .thenReturn(mockWriter); + SerializationWriterFactoryRegistry + .defaultInstance.contentTypeAssociatedFactories + .putIfAbsent(contentType, () => mockFactory); + final serializationWriter = SerializationWriterFactoryRegistry + .defaultInstance + .getSerializationWriter('application/vnd+text'); expect(serializationWriter, isNotNull); }); }); diff --git a/packages/kiota_serialization_form/lib/src/form_serialization_writer.dart b/packages/kiota_serialization_form/lib/src/form_serialization_writer.dart index 90e89c2..5691c50 100644 --- a/packages/kiota_serialization_form/lib/src/form_serialization_writer.dart +++ b/packages/kiota_serialization_form/lib/src/form_serialization_writer.dart @@ -168,7 +168,7 @@ class FormSerializationWriter implements SerializationWriter { if (additionalValuesToMerge != null) { for (final additionalValue in additionalValuesToMerge) { - if(additionalValue != null){ + if (additionalValue != null) { onBeforeObjectSerialization?.call(additionalValue); onStartObjectSerialization?.call(additionalValue, this); diff --git a/packages/kiota_serialization_form/test/form_parse_node_test.dart b/packages/kiota_serialization_form/test/form_parse_node_test.dart index 020c93d..6cd9342 100644 --- a/packages/kiota_serialization_form/test/form_parse_node_test.dart +++ b/packages/kiota_serialization_form/test/form_parse_node_test.dart @@ -85,7 +85,7 @@ void main() { expect( node.getGuidValue(), - equals(UuidValue.nil), + equals(UuidValue.fromString('00000000-0000-0000-0000-000000000000')), ); }); diff --git a/packages/kiota_serialization_json/lib/src/json_parse_node.dart b/packages/kiota_serialization_json/lib/src/json_parse_node.dart index 5f6cdaa..c887f2d 100644 --- a/packages/kiota_serialization_json/lib/src/json_parse_node.dart +++ b/packages/kiota_serialization_json/lib/src/json_parse_node.dart @@ -170,7 +170,7 @@ class JsonParseNode implements ParseNode { UntypedNode? getUntypedValue(dynamic node) { if (node == null) { - return UntypedNull(); + return const UntypedNull(); } if (node is List) { diff --git a/packages/kiota_serialization_json/test/intersection_type_test.dart b/packages/kiota_serialization_json/test/intersection_type_test.dart index 842f134..fa83504 100644 --- a/packages/kiota_serialization_json/test/intersection_type_test.dart +++ b/packages/kiota_serialization_json/test/intersection_type_test.dart @@ -101,8 +101,10 @@ void main() { ..serialize(writer); final content = writer.getSerializedContent(); final result = utf8.decode(content); - expect(result, - '{"id":"opaque","officeLocation":"Montreal","displayName":"McGill"}'); + expect( + result, + '{"id":"opaque","officeLocation":"Montreal","displayName":"McGill"}', + ); }); test('SerializeIntersectionTypeComplexProperty2', () { @@ -132,8 +134,10 @@ void main() { ..serialize(writer); final content = writer.getSerializedContent(); final result = utf8.decode(content); - expect(result, - '[{"id":"10","namingEnum":"Item2:SubItem1","officeLocation":"Montreal"},{"id":"11","namingEnum":"Item3:SubItem1","officeLocation":"Ottawa"}]'); + expect( + result, + '[{"id":"10","namingEnum":"Item2:SubItem1","officeLocation":"Montreal"},{"id":"11","namingEnum":"Item3:SubItem1","officeLocation":"Ottawa"}]', + ); }); }); } diff --git a/packages/kiota_serialization_json/test/json_parse_node_factory_test.dart b/packages/kiota_serialization_json/test/json_parse_node_factory_test.dart index b8d4ab1..7dc39be 100644 --- a/packages/kiota_serialization_json/test/json_parse_node_factory_test.dart +++ b/packages/kiota_serialization_json/test/json_parse_node_factory_test.dart @@ -8,17 +8,19 @@ void main() { test('getParseNodeForJsonContentType', () { final json = utf8.encode('{"key":"value"}'); final factory = JsonParseNodeFactory(); - final JsonParseNode = + final jsonParseNode = factory.getRootParseNode(factory.validContentType, json); - expect(JsonParseNode, isNotNull); + expect(jsonParseNode, isNotNull); }); test('testThrowsExceptionForInvalidContentType', () { const streamContentType = 'application/octet-stream'; final json = utf8.encode('{"key":"value"}'); final factory = JsonParseNodeFactory(); - expect(() => factory.getRootParseNode(streamContentType, json), - throwsArgumentError); + expect( + () => factory.getRootParseNode(streamContentType, json), + throwsArgumentError, + ); }); }); } diff --git a/packages/kiota_serialization_json/test/json_parse_node_test.dart b/packages/kiota_serialization_json/test/json_parse_node_test.dart index ce1b77f..2a34b0a 100644 --- a/packages/kiota_serialization_json/test/json_parse_node_test.dart +++ b/packages/kiota_serialization_json/test/json_parse_node_test.dart @@ -168,8 +168,10 @@ void main() { test('Get enumcollection from json', () { final jsonParseNode = JsonParseNode(jsonDecode(_testCollectionOfEnumsJson)); - final testCollection = jsonParseNode.getCollectionOfEnumValues((value) => - NamingEnum.values.where((ne) => ne.value == value).firstOrNull); + final testCollection = jsonParseNode.getCollectionOfEnumValues( + (value) => + NamingEnum.values.where((ne) => ne.value == value).firstOrNull, + ); expect(testCollection, isNotNull); expect(testCollection.length, 2); diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_factory_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_factory_test.dart index e51afda..06f6795 100644 --- a/packages/kiota_serialization_json/test/json_serialization_writer_factory_test.dart +++ b/packages/kiota_serialization_json/test/json_serialization_writer_factory_test.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; -import 'package:kiota_abstractions/kiota_abstractions.dart'; import 'package:kiota_serialization_json/kiota_serialization_json.dart'; import 'package:test/test.dart'; @@ -15,8 +13,10 @@ void main() { test('testThrowsExceptionForInvalidContentType', () { const streamContentType = 'application/octet-stream'; final factory = JsonSerializationWriterFactory(); - expect(() => factory.getSerializationWriter(streamContentType), - throwsArgumentError); + expect( + () => factory.getSerializationWriter(streamContentType), + throwsArgumentError, + ); }); }); } diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart index dcd051f..2a237d6 100644 --- a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart +++ b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart @@ -59,7 +59,8 @@ void main() { expect( utf8.decode(writer.getSerializedContent()), equals( - '{"id":"abc","createdDateTime":"2023-12-01T15:15:00.000","officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":1.7,"startWorkTime":"06:00:00","active":true,"numbers":[2,3,5],"a":"some value","b":12,"c":false}'), + '{"id":"abc","createdDateTime":"2023-12-01T15:15:00.000","officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":1.7,"startWorkTime":"06:00:00","active":true,"numbers":[2,3,5],"a":"some value","b":12,"c":false}', + ), ); }); @@ -88,7 +89,8 @@ void main() { expect( utf8.decode(writer.getSerializedContent()), equals( - '{"name":"a group","leader":{"heightInMetres":1.9,"endWorkTime":"17:00:00"},"members":[{"officeLocation":"on a chair","workDuration":"2:00:00.000000","a":"#1 coworker"},{"workDuration":"12:00:00.000000","active":true}]}'), + '{"name":"a group","leader":{"heightInMetres":1.9,"endWorkTime":"17:00:00"},"members":[{"officeLocation":"on a chair","workDuration":"2:00:00.000000","a":"#1 coworker"},{"workDuration":"12:00:00.000000","active":true}]}', + ), ); }); }); diff --git a/packages/kiota_serialization_json/test/microsoft_graph_group.dart b/packages/kiota_serialization_json/test/microsoft_graph_group.dart index c27f6c8..f6f6cf9 100644 --- a/packages/kiota_serialization_json/test/microsoft_graph_group.dart +++ b/packages/kiota_serialization_json/test/microsoft_graph_group.dart @@ -30,7 +30,8 @@ class MicrosoftGraphGroup extends Parsable implements AdditionalDataHolder { 'leader': (node) => leader = node.getObjectValue(MicrosoftGraphUser.createFromDiscriminator), 'members': (node) => members = node.getCollectionOfObjectValues( - MicrosoftGraphUser.createFromDiscriminator), + MicrosoftGraphUser.createFromDiscriminator, + ), }; } diff --git a/packages/kiota_serialization_json/test/second_test_entity.dart b/packages/kiota_serialization_json/test/second_test_entity.dart index de37066..dd9043e 100644 --- a/packages/kiota_serialization_json/test/second_test_entity.dart +++ b/packages/kiota_serialization_json/test/second_test_entity.dart @@ -3,7 +3,7 @@ import 'package:kiota_abstractions/kiota_abstractions.dart'; class SecondTestEntity extends Parsable implements AdditionalDataHolder { SecondTestEntity(); - factory SecondTestEntity.createFromDiscriminatorValue(ParseNode parseNode) { + factory SecondTestEntity.createFromDiscriminatorValue(ParseNode _) { return SecondTestEntity(); } @@ -25,9 +25,9 @@ class SecondTestEntity extends Parsable implements AdditionalDataHolder { @override void serialize(SerializationWriter writer) { writer - ..writeStringValue("displayName", displayName) - ..writeIntValue("id", id) - ..writeIntValue("failureRate", failureRate) + ..writeStringValue('displayName', displayName) + ..writeIntValue('id', id) + ..writeIntValue('failureRate', failureRate) ..writeAdditionalData(additionalData); } } diff --git a/packages/kiota_serialization_json/test/union_type_mock.dart b/packages/kiota_serialization_json/test/union_type_mock.dart index 2b38a75..a5e0d17 100644 --- a/packages/kiota_serialization_json/test/union_type_mock.dart +++ b/packages/kiota_serialization_json/test/union_type_mock.dart @@ -20,11 +20,13 @@ class UnionTypeMock extends Parsable implements AdditionalDataHolder { result.stringValue = parseNode.getStringValue(); } else if (parseNode .getCollectionOfObjectValues( - MicrosoftGraphUser.createFromDiscriminator) + MicrosoftGraphUser.createFromDiscriminator, + ) .isNotEmpty) { result.composedType3 = parseNode.getCollectionOfObjectValues( - MicrosoftGraphUser.createFromDiscriminator); + MicrosoftGraphUser.createFromDiscriminator, + ); } return result; } diff --git a/packages/kiota_serialization_json/test/union_type_test.dart b/packages/kiota_serialization_json/test/union_type_test.dart index 927d314..1000209 100644 --- a/packages/kiota_serialization_json/test/union_type_test.dart +++ b/packages/kiota_serialization_json/test/union_type_test.dart @@ -127,8 +127,10 @@ void main() { ..serialize(writer); final content = writer.getSerializedContent(); final result = utf8.decode(content); - expect(result, - '[{"id":"10","officeLocation":"Montreal"},{"id":"11","officeLocation":"Ottawa"}]'); + expect( + result, + '[{"id":"10","officeLocation":"Montreal"},{"id":"11","officeLocation":"Ottawa"}]', + ); }); }); } diff --git a/packages/kiota_serialization_text/test/text_parse_node_test.dart b/packages/kiota_serialization_text/test/text_parse_node_test.dart index a7f338d..8124c7d 100644 --- a/packages/kiota_serialization_text/test/text_parse_node_test.dart +++ b/packages/kiota_serialization_text/test/text_parse_node_test.dart @@ -88,7 +88,7 @@ void main() { expect( node.getGuidValue(), - equals(UuidValue.nil), + equals(UuidValue.fromString('00000000-0000-0000-0000-000000000000')), ); }); From ea03d2919181397c335b19cc2443a416966e320d Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 12 Nov 2024 16:10:06 +0100 Subject: [PATCH 59/69] Added entries for json to codeowners and makefile --- .github/CODEOWNERS | 1 + Makefile | 15 ++++++++++++--- packages/kiota_serialization_json/pubspec.yaml | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0cf424c..f2b9b32 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1,2 @@ * @ricardoboss +/packages/kiota_serialization_json @joanne-ter-maat \ No newline at end of file diff --git a/Makefile b/Makefile index a385a11..aecc558 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -pub-get: pub-get-abstractions pub-get-http pub-get-serialization-text pub-get-serialization-form +pub-get: pub-get-abstractions pub-get-http pub-get-serialization-text pub-get-serialization-form pub-get-serialization-json pub-get-abstractions: cd packages/kiota_abstractions && dart pub get @@ -12,10 +12,13 @@ pub-get-serialization-text: pub-get-serialization-form: cd packages/kiota_serialization_form && dart pub get +pub-get-serialization-json: + cd packages/kiota_serialization_json && dart pub get + format: dart format packages -generate: generate-abstractions generate-http generate-serialization-form +generate: generate-abstractions generate-http generate-serialization-form generate-serialization-json generate-abstractions: cd packages/kiota_abstractions && dart run build_runner build --delete-conflicting-outputs @@ -26,7 +29,10 @@ generate-http: generate-serialization-form: cd packages/kiota_serialization_form && dart run build_runner build --delete-conflicting-outputs -test: test-abstractions test-http test-serialization-text test-serialization-form +generate-serialization-json: + cd packages/kiota_serialization_json && dart run build_runner build --delete-conflicting-outputs + +test: test-abstractions test-http test-serialization-text test-serialization-form test-serialization-json test-abstractions: pub-get-abstractions generate-abstractions cd packages/kiota_abstractions && dart test @@ -39,3 +45,6 @@ test-serialization-text: pub-get-serialization-text test-serialization-form: pub-get-serialization-form generate-serialization-form cd packages/kiota_serialization_form && dart test + +test-serialization-json: pub-get-serialization-json generate-serialization-json + cd packages/kiota_serialization_json && dart test \ No newline at end of file diff --git a/packages/kiota_serialization_json/pubspec.yaml b/packages/kiota_serialization_json/pubspec.yaml index b8a2779..a7d51cc 100644 --- a/packages/kiota_serialization_json/pubspec.yaml +++ b/packages/kiota_serialization_json/pubspec.yaml @@ -15,5 +15,6 @@ dependencies: uuid: ^4.4.2 dev_dependencies: + build_runner: ^2.4.9 strict: ^2.0.0 test: ^1.25.2 From f955cdcfc87168a35c108630c52f550dcc0d7687 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Tue, 12 Nov 2024 16:10:53 +0100 Subject: [PATCH 60/69] Simpler solution for json serialization writer --- .../lib/src/json_serialization_writer.dart | 132 ++++-------------- 1 file changed, 30 insertions(+), 102 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index a26a7f8..6b8975e 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -1,7 +1,7 @@ part of '../kiota_serialization_json.dart'; class JsonSerializationWriter implements SerializationWriter { - final List _buffer = []; + final Map _contents = {}; final openingObject = '{'; final closingObject = '}'; @@ -20,19 +20,16 @@ class JsonSerializationWriter implements SerializationWriter { @override Uint8List getSerializedContent() { - removeSeparator(); - return utf8.encode(_buffer.join()); + if (_contents.length == 1 && _contents.keys.first == '') { + return utf8.encode(jsonEncode(_contents.values.first)); + } + return utf8.encode(jsonEncode(_contents)); } @override void writeAdditionalData(Map value) { for (final entry in value.entries) { - if (entry.value is bool || entry.value is int || entry.value is double) { - _buffer.add('"${entry.key}":${entry.value}'); - } else { - _buffer.add('"${entry.key}":"${_getAnyValue(entry.value as Object)}"'); - } - _buffer.add(separator); + _contents[entry.key] = entry.value; } } @@ -55,22 +52,11 @@ class JsonSerializationWriter implements SerializationWriter { if (values == null || values.isEmpty) { return; } else { - final writeAsObject = _buffer.isEmpty; - final opening = writeAsObject ? openingObject : ''; - _buffer.add('$opening"$key":$openingArray'); - var first = true; + final enumList = []; for (final value in values) { - if (!first) { - _buffer.add(separator); - } - first = false; - _buffer.add('"${serializer(value)}"'); + enumList.add(serializer(value)); } - _buffer.add(closingArray); - if (writeAsObject) { - _buffer.add(closingObject); - } - _buffer.add(separator); + _contents[key ?? ''] = enumList; } } @@ -82,25 +68,16 @@ class JsonSerializationWriter implements SerializationWriter { if (values == null || values.isEmpty) { return; } else { - if (key?.isEmpty ?? true) { - _buffer.add(openingArray); - } else { - _buffer.add('"$key":$openingArray'); - } - var first = true; + final originalContents = {..._contents}; + _contents.clear(); + final objects = []; for (final value in values) { - if (!first) { - _buffer.add(separator); - } - first = false; - _buffer.add(openingObject); value.serialize(this); - removeSeparator(); - _buffer.add(closingObject); + objects.add({..._contents}); + _contents.clear(); } - _buffer - ..add(closingArray) - ..add(separator); + _contents.addAll(originalContents); + _contents[key ?? ''] = objects; } } @@ -109,26 +86,7 @@ class JsonSerializationWriter implements SerializationWriter { if (values == null || values.isEmpty) { return; } else { - final writeAsObject = _buffer.isEmpty; - final opening = writeAsObject ? openingObject : ''; - _buffer.add('$opening"$key":$openingArray'); - var first = true; - for (final value in values) { - if (!first) { - _buffer.add(separator); - } - first = false; - if (value is bool || value is int || value is double) { - _buffer.add('$value'); - } else { - _buffer.add('"${_getAnyValue(value!)}"'); - } - } - _buffer.add(closingArray); - if (writeAsObject) { - _buffer.add(closingObject); - } - _buffer.add(separator); + _contents[key ?? ''] = values; } } @@ -173,11 +131,10 @@ class JsonSerializationWriter implements SerializationWriter { if (value != null) { onBeforeObjectSerialization?.call(value); } - - if (key == null) { - _buffer.add(openingObject); - } else { - _buffer.add('"$key":$openingObject'); + var originalContents = {}; + if (key?.isNotEmpty ?? false) { + originalContents = {..._contents}; + _contents.clear(); } if (value != null) { onStartObjectSerialization?.call(value, this); @@ -195,12 +152,16 @@ class JsonSerializationWriter implements SerializationWriter { } } } - removeSeparator(); - _buffer.add(closingObject); + if (key?.isNotEmpty ?? false) { + final objectContents = {..._contents}; + _contents + ..clear() + ..addAll(originalContents); + _contents[key ?? ''] = objectContents; + } if (value != null) { onAfterObjectSerialization?.call(value); } - _buffer.add(separator); } @override @@ -209,15 +170,7 @@ class JsonSerializationWriter implements SerializationWriter { if (value?.isEmpty ?? true) { return; } - if (key?.isEmpty ?? true) { - _buffer - ..add('"$value"') - ..add(separator); - } else { - _buffer - ..add('"$key":"$value"') - ..add(separator); - } + _contents[key ?? ''] = value; } void writeUnquotedValue(String? key, Object? value) { @@ -228,9 +181,7 @@ class JsonSerializationWriter implements SerializationWriter { if (value == null) { return; } - _buffer - ..add('"$key":$value') - ..add(separator); + _contents[key!] = value; } @override @@ -252,27 +203,4 @@ class JsonSerializationWriter implements SerializationWriter { void writeUuidValue(String? key, UuidValue? value) { writeStringValue(key, value?.uuid); } - - void removeSeparator() { - if (_buffer.last == separator) { - _buffer.removeLast(); - } - } - - String _getAnyValue(Object value) { - switch (value) { - case final String s: - return s; - case final UuidValue u: - return u.uuid; - case final DateTime d: - return d.toIso8601String(); - case final DateOnly d: - return d.toRfc3339String(); - case final TimeOnly t: - return t.toRfc3339String(); - default: - return value.toString(); - } - } } From 9acf83e84801d0ccdc92338e42b7873aab192b25 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 13 Nov 2024 11:37:23 +0100 Subject: [PATCH 61/69] process untyped nodes in the serialization writer --- .../src/serialization/untyped_boolean.dart | 5 ++ .../lib/src/serialization/untyped_double.dart | 5 ++ .../src/serialization/untyped_integer.dart | 5 ++ .../lib/src/serialization/untyped_string.dart | 5 ++ .../lib/src/json_serialization_writer.dart | 46 ++++++++++++++++++- .../test/json_serialization_writer_test.dart | 13 +++++- 6 files changed, 75 insertions(+), 4 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_boolean.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_boolean.dart index 9e08e54..cb687a6 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_boolean.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_boolean.dart @@ -4,4 +4,9 @@ class UntypedBoolean extends UntypedNode { const UntypedBoolean({required this.value}); final bool value; + + @override + bool? getValue() { + return value; + } } diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_double.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_double.dart index e7dfc74..6eb34ed 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_double.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_double.dart @@ -4,4 +4,9 @@ class UntypedDouble extends UntypedNode { const UntypedDouble(this.value); final double value; + + @override + double? getValue() { + return value; + } } diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_integer.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_integer.dart index 5d431ef..588c304 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_integer.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_integer.dart @@ -4,4 +4,9 @@ class UntypedInteger extends UntypedNode { const UntypedInteger(this.value); final int value; + + @override + int? getValue() { + return value; + } } diff --git a/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart b/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart index 4dfa6b8..f4ebd16 100644 --- a/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart +++ b/packages/kiota_abstractions/lib/src/serialization/untyped_string.dart @@ -4,4 +4,9 @@ class UntypedString extends UntypedNode { const UntypedString(this.value); final String value; + + @override + String? getValue() { + return value; + } } diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index 6b8975e..e62c4ef 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -29,7 +29,11 @@ class JsonSerializationWriter implements SerializationWriter { @override void writeAdditionalData(Map value) { for (final entry in value.entries) { - _contents[entry.key] = entry.value; + if (entry.value is UntypedNode) { + writeUntypedValue(entry.key, entry.value as UntypedNode); + } else { + _contents[entry.key] = entry.value; + } } } @@ -138,7 +142,11 @@ class JsonSerializationWriter implements SerializationWriter { } if (value != null) { onStartObjectSerialization?.call(value, this); - value.serialize(this); + if (value is UntypedNode) { + writeUntypedValue(key, value as UntypedNode); + } else { + value.serialize(this); + } } if (additionalValuesToMerge != null) { for (final additionalValue in additionalValuesToMerge) { @@ -203,4 +211,38 @@ class JsonSerializationWriter implements SerializationWriter { void writeUuidValue(String? key, UuidValue? value) { writeStringValue(key, value?.uuid); } + + void writeUntypedValue(String? key, UntypedNode untypedValue) { + if (untypedValue is UntypedString) { + writeStringValue(key, untypedValue.value); + } else if (untypedValue is UntypedNull) { + writeNullValue(key); + } else if (untypedValue is UntypedBoolean) { + writeBoolValue(key, value: untypedValue.value); + } else if (untypedValue is UntypedDouble) { + writeDoubleValue(key, untypedValue.value); + } else if (untypedValue is UntypedInteger) { + writeIntValue(key, untypedValue.value); + } else if (untypedValue is UntypedObject) { + writeUntypedObject(key, untypedValue); + } else if (untypedValue is UntypedArray) { + writeUntypedArray(key, untypedValue); + } + } + + void writeUntypedObject(String? key, UntypedObject value) { + final objectProperties = {}; + for (final entry in value.properties.entries) { + objectProperties[entry.key] = entry.value.getValue(); + } + _contents[key ?? ''] = objectProperties; + } + + void writeUntypedArray(String? key, UntypedArray value) { + final arrayEntries = []; + for (final entry in value.getValue()) { + arrayEntries.add(entry.getValue()); + } + _contents[key ?? ''] = arrayEntries; + } } diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart index 2a237d6..dd4f18a 100644 --- a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart +++ b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart @@ -37,6 +37,7 @@ void main() { }); test('writeObject', () { + const untypedNodesList = [UntypedString('abc'), UntypedDouble(8.8)]; final simpleUser = MicrosoftGraphUser() ..id = 'abc' ..createdDateTime = DateTime(2023, 12, 1, 15, 15) @@ -48,7 +49,15 @@ void main() { ..startWorkTime = TimeOnly.fromDateTimeString('06:00') ..active = true ..numbers = [2, 3, 5] - ..additionalData = {'a': 'some value', 'b': 12, 'c': false}; + ..additionalData = { + 'a': 'some value', + 'b': 12, + 'c': false, + 'someNull': const UntypedNull(), + 'untypedArray': const UntypedArray(untypedNodesList), + 'object': const UntypedObject( + {'name': UntypedString('a name'), 'age': UntypedInteger(8)}) + }; final writer = JsonSerializationWriter() ..writeObjectValue( @@ -59,7 +68,7 @@ void main() { expect( utf8.decode(writer.getSerializedContent()), equals( - '{"id":"abc","createdDateTime":"2023-12-01T15:15:00.000","officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":1.7,"startWorkTime":"06:00:00","active":true,"numbers":[2,3,5],"a":"some value","b":12,"c":false}', + '{"id":"abc","createdDateTime":"2023-12-01T15:15:00.000","officeLocation":"at the desk","workDuration":"40:00:00.000000","birthDay":"2024-10-01","heightInMetres":1.7,"startWorkTime":"06:00:00","active":true,"numbers":[2,3,5],"a":"some value","b":12,"c":false,"someNull":"null","untypedArray":["abc",8.8],"object":{"name":"a name","age":8}}', ), ); }); From bf7e305c1b351931e156467ba9cdfd9ecee99ca4 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Wed, 13 Nov 2024 13:20:56 +0100 Subject: [PATCH 62/69] Added myself to CODEOWNERS as requested by Ricardo --- .github/CODEOWNERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f2b9b32..5a3757b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,3 @@ * @ricardoboss -/packages/kiota_serialization_json @joanne-ter-maat \ No newline at end of file +/packages/kiota_serialization_json @joanne-ter-maat +/packages/kiota_serialization_multipart @Kees-Schotanus \ No newline at end of file From 09cff4f14fbd66b0d08a8cd2285ed388a237305a Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Wed, 13 Nov 2024 14:08:28 +0100 Subject: [PATCH 63/69] Added type to variable --- .../lib/src/json_serialization_writer.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index e62c4ef..ecc75d4 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -74,7 +74,7 @@ class JsonSerializationWriter implements SerializationWriter { } else { final originalContents = {..._contents}; _contents.clear(); - final objects = []; + final List> objects = []; for (final value in values) { value.serialize(this); objects.add({..._contents}); From 737004906c63eaceed6cb17f3174be945e4c4458 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Thu, 14 Nov 2024 10:12:00 +0100 Subject: [PATCH 64/69] Not all datatypes are directly usable in jsonEncode, correct for this in writeAdditionalData --- .../lib/src/json_serialization_writer.dart | 33 ++++++++++-------- .../test/json_serialization_writer_test.dart | 34 +++++++++++++++++++ ...ultipart_serialization_writer_factory.dart | 3 +- .../multipart_serialization_writer_test.dart | 2 +- .../test/test_entity.dart | 3 +- 5 files changed, 58 insertions(+), 17 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index ecc75d4..17f0551 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -31,6 +31,16 @@ class JsonSerializationWriter implements SerializationWriter { for (final entry in value.entries) { if (entry.value is UntypedNode) { writeUntypedValue(entry.key, entry.value as UntypedNode); + } else if (entry.value is DateTime) { + writeDateTimeValue(entry.key, entry.value as DateTime); + } else if (entry.value is DateOnly) { + writeDateOnlyValue(entry.key, entry.value as DateOnly); + } else if (entry.value is TimeOnly) { + writeTimeOnlyValue(entry.key, entry.value as TimeOnly); + } else if (entry.value is Parsable) { + writeObjectValue(entry.key, entry.value as Parsable); + } else if (entry.value is UuidValue) { + writeUuidValue(entry.key, entry.value as UuidValue); } else { _contents[entry.key] = entry.value; } @@ -39,7 +49,9 @@ class JsonSerializationWriter implements SerializationWriter { @override void writeBoolValue(String? key, {bool? value}) { - writeUnquotedValue(key, value); + if (value != null) { + _contents[key ?? ''] = value; + } } @override @@ -101,7 +113,9 @@ class JsonSerializationWriter implements SerializationWriter { @override void writeDoubleValue(String? key, double? value) { - writeUnquotedValue(key, value); + if (value != null) { + _contents[key ?? ''] = value; + } } @override @@ -115,7 +129,9 @@ class JsonSerializationWriter implements SerializationWriter { @override void writeIntValue(String? key, int? value) { - writeUnquotedValue(key, value); + if (value != null) { + _contents[key ?? ''] = value; + } } @override @@ -181,17 +197,6 @@ class JsonSerializationWriter implements SerializationWriter { _contents[key ?? ''] = value; } - void writeUnquotedValue(String? key, Object? value) { - if (key?.isEmpty ?? true) { - return; - } - // if the value is null or empty, we don't write anything - if (value == null) { - return; - } - _contents[key!] = value; - } - @override void writeDateOnlyValue(String? key, DateOnly? value) { writeStringValue(key, value?.toRfc3339String()); diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart index dd4f18a..d80c5b0 100644 --- a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart +++ b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:kiota_abstractions/kiota_abstractions.dart'; import 'package:kiota_serialization_json/kiota_serialization_json.dart'; import 'package:test/test.dart'; +import 'package:uuid/uuid.dart'; import 'microsoft_graph_group.dart'; import 'microsoft_graph_user.dart'; @@ -102,5 +103,38 @@ void main() { ), ); }); + + test('writeAdditionalDataTypes', () { + final user2 = MicrosoftGraphUser() + ..workDuration = const Duration(hours: 12) + ..active = true; + final user = MicrosoftGraphUser() + ..officeLocation = '' + ..workDuration = const Duration(hours: 2) + ..additionalData = { + 'a': '#1 coworker', + 'string': 'a string', + 'double': 0.0, + 'bool': false, + 'time': TimeOnly.fromComponents(12, 00), + 'date': DateOnly.fromComponents(2000), + 'datetime': DateTime(2024, 12, 31, 23, 59), + 'uuid': UuidValue.fromString('019329eb-0ac5-7cc0-9dea-6440b3648264'), + 'user': user2, + }; + + final writer = JsonSerializationWriter() + ..writeObjectValue( + null, + user, + ); + + expect( + utf8.decode(writer.getSerializedContent()), + equals( + '{"workDuration":"2:00:00.000000","a":"#1 coworker","string":"a string","double":0.0,"bool":false,"time":"12:00:00","date":"2000-01-01","datetime":"2024-12-31T23:59:00.000","uuid":"019329eb-0ac5-7cc0-9dea-6440b3648264","user":{"workDuration":"12:00:00.000000","active":true}}', + ), + ); + }); }); } diff --git a/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer_factory.dart b/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer_factory.dart index dc3184d..c41f5e1 100644 --- a/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer_factory.dart +++ b/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer_factory.dart @@ -1,6 +1,7 @@ part of '../kiota_serialization_multipart.dart'; -class MultipartSerializationWriterFactory implements SerializationWriterFactory { +class MultipartSerializationWriterFactory + implements SerializationWriterFactory { @override SerializationWriter getSerializationWriter(String contentType) { if (contentType.toLowerCase() != validContentType) { diff --git a/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart b/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart index b06ea52..894d20c 100644 --- a/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart +++ b/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart @@ -67,7 +67,7 @@ void main() { final serializationWriter = MultipartSerializationWriter() ..writeObjectValue(null, multipartBody); final stringContent = - String.fromCharCodes(serializationWriter.getSerializedContent()); + String.fromCharCodes(serializationWriter.getSerializedContent()); final expected = ''' --${multipartBody.boundary}\r diff --git a/packages/kiota_serialization_multipart/test/test_entity.dart b/packages/kiota_serialization_multipart/test/test_entity.dart index 86531d1..60d2dc8 100644 --- a/packages/kiota_serialization_multipart/test/test_entity.dart +++ b/packages/kiota_serialization_multipart/test/test_entity.dart @@ -28,7 +28,8 @@ class TestEntity implements Parsable, AdditionalDataHolder { 'id': (node) => id = node.getStringValue(), 'officeLocation': (node) => officeLocation = node.getStringValue(), 'birthDay': (node) => birthDay = node.getDateOnlyValue(), - 'deviceNames': (node) => deviceNames = node.getCollectionOfPrimitiveValues(), + 'deviceNames': (node) => + deviceNames = node.getCollectionOfPrimitiveValues(), 'workDuration': (node) => workDuration = node.getDurationValue(), 'startWorkTime': (node) => startWorkTime = node.getTimeOnlyValue(), 'endWorkTime': (node) => endWorkTime = node.getTimeOnlyValue(), From 90de047d47c22f6101e5cadf55468bfc99788aa4 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Thu, 14 Nov 2024 10:38:44 +0100 Subject: [PATCH 65/69] Enhance writeObjectValue Instead of checking just the header, the complete serialized object is now verified. --- .../test/multipart_serialization_writer_test.dart | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart b/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart index 894d20c..c99c66a 100644 --- a/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart +++ b/packages/kiota_serialization_multipart/test/multipart_serialization_writer_test.dart @@ -72,9 +72,18 @@ void main() { final expected = ''' --${multipartBody.boundary}\r Content-Type: application/json\r -Content-Disposition: form-data; name="testEntity"'''; +Content-Disposition: form-data; name="testEntity"\r +\r +{"id":"48e31887-5dad-4d73-a9f5-3c356e68a038","birthDay":"1961-09-29","workDuration":"8:00:00.000000","startWorkTime":"06:30:00","endWorkTime":"15:00:00","deviceNames":["device1","device2"],"mobilePhone":null,"jobTitle":"Author","accountEnabled":false,"createdDateTime":"1961-09-29T08:31:00.000","otherPhones":["device1","device2"]}\r +--${multipartBody.boundary}\r +Content-Type: application/octet-stream\r +Content-Disposition: form-data; name="image"\r +\r +\u0001\u0002\u0003\r +--${multipartBody.boundary}--\r +'''; - expect(stringContent.substring(0, expected.length), expected); + expect(stringContent, expected); }); }); } From 52d26a89341645f62c0ca7fd3f4e87c6d63821c3 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Thu, 14 Nov 2024 10:51:02 +0100 Subject: [PATCH 66/69] Fixed cosmetic changes noted by analyzer --- .../lib/src/api_client_builder.dart | 16 +++++----- .../test/api_client_builder_test.dart | 30 +++++++++---------- .../lib/src/http_client_request_adapter.dart | 2 +- .../test/json_serialization_writer_test.dart | 2 +- .../src/multipart_serialization_writer.dart | 4 +-- .../test/test_entity.dart | 2 +- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/api_client_builder.dart b/packages/kiota_abstractions/lib/src/api_client_builder.dart index 3014a69..f0f4738 100644 --- a/packages/kiota_abstractions/lib/src/api_client_builder.dart +++ b/packages/kiota_abstractions/lib/src/api_client_builder.dart @@ -26,14 +26,14 @@ class ApiClientBuilder { static SerializationWriterFactory enableBackingStoreForSerializationWriterFactory( - SerializationWriterFactory original) { + SerializationWriterFactory original,) { var result = original; if (original is SerializationWriterFactoryRegistry) { _enableBackingStoreForSerializationRegistry(original); if (original != SerializationWriterFactoryRegistry.defaultInstance) { // if the registry is the default instance, we already enabled it above. No need to do it twice _enableBackingStoreForSerializationRegistry( - SerializationWriterFactoryRegistry.defaultInstance); + SerializationWriterFactoryRegistry.defaultInstance,); } } if (result is BackingStoreSerializationWriterProxyFactory) { @@ -47,14 +47,14 @@ class ApiClientBuilder { } static ParseNodeFactory enableBackingStoreForParseNodeFactory( - ParseNodeFactory original) { + ParseNodeFactory original,) { var result = original; if (original is ParseNodeFactoryRegistry) { _enableBackingStoreForParseNodeRegistry(original); if (original != ParseNodeFactoryRegistry.defaultInstance) { // if the registry is the default instance, we already enabled it above. No need to do it twice _enableBackingStoreForParseNodeRegistry( - ParseNodeFactoryRegistry.defaultInstance); + ParseNodeFactoryRegistry.defaultInstance,); } } if (result is BackingStoreParseNodeFactory) { @@ -68,7 +68,7 @@ class ApiClientBuilder { } static void _enableBackingStoreForParseNodeRegistry( - ParseNodeFactoryRegistry registry) { + ParseNodeFactoryRegistry registry,) { final keysToUpdate = []; registry.contentTypeAssociatedFactories.forEach((key, value) { if (value is! BackingStoreParseNodeFactory) { @@ -79,12 +79,12 @@ class ApiClientBuilder { keysToUpdate.forEach((key) { registry.contentTypeAssociatedFactories[key] = BackingStoreParseNodeFactory( - concrete: registry.contentTypeAssociatedFactories[key]!); + concrete: registry.contentTypeAssociatedFactories[key]!,); }); } static void _enableBackingStoreForSerializationRegistry( - SerializationWriterFactoryRegistry registry) { + SerializationWriterFactoryRegistry registry,) { final keysToUpdate = []; registry.contentTypeAssociatedFactories.forEach((key, value) { { @@ -97,7 +97,7 @@ class ApiClientBuilder { keysToUpdate.forEach((key) { registry.contentTypeAssociatedFactories[key] = BackingStoreSerializationWriterProxyFactory( - concrete: registry.contentTypeAssociatedFactories[key]!); + concrete: registry.contentTypeAssociatedFactories[key]!,); }); } } diff --git a/packages/kiota_abstractions/test/api_client_builder_test.dart b/packages/kiota_abstractions/test/api_client_builder_test.dart index af16bab..1f20ae9 100644 --- a/packages/kiota_abstractions/test/api_client_builder_test.dart +++ b/packages/kiota_abstractions/test/api_client_builder_test.dart @@ -4,7 +4,7 @@ import 'package:test/test.dart'; import 'api_client_builder_test.mocks.dart'; @GenerateMocks( - [SerializationWriter, SerializationWriterFactory, ParseNodeFactory]) + [SerializationWriter, SerializationWriterFactory, ParseNodeFactory],) void main() { const streamContentType = 'application/octet-stream'; @@ -19,17 +19,17 @@ void main() { serializationFactoryRegistry .contentTypeAssociatedFactories[streamContentType] is BackingStoreSerializationWriterProxyFactory, - isFalse); + isFalse,); // Act ApiClientBuilder.enableBackingStoreForSerializationWriterFactory( - serializationFactoryRegistry); + serializationFactoryRegistry,); // Assert the type has changed due to backing store enabling expect( serializationFactoryRegistry .contentTypeAssociatedFactories[streamContentType], - isA()); + isA(),); }); test( 'enableBackingStoreForSerializationWriterFactoryAlsoEnablesForDefaultInstance', @@ -46,22 +46,22 @@ void main() { serializationFactoryRegistry .contentTypeAssociatedFactories[streamContentType] is BackingStoreSerializationWriterProxyFactory, - isFalse); + isFalse,); // Act ApiClientBuilder.enableBackingStoreForSerializationWriterFactory( - serializationFactoryRegistry); + serializationFactoryRegistry,); // Assert the type has changed due to backing store enabling expect( serializationFactoryRegistry .contentTypeAssociatedFactories[streamContentType], - isA()); + isA(),); expect( SerializationWriterFactoryRegistry.defaultInstance .contentTypeAssociatedFactories[streamContentType], - isA()); + isA(),); }); test('enableBackingStoreForParseNodeFactory', () { final parseNodeRegistry = ParseNodeFactoryRegistry(); @@ -71,7 +71,7 @@ void main() { expect( parseNodeRegistry.contentTypeAssociatedFactories[streamContentType] is BackingStoreParseNodeFactory, - isFalse); + isFalse,); // Act ApiClientBuilder.enableBackingStoreForParseNodeFactory(parseNodeRegistry); @@ -79,7 +79,7 @@ void main() { // Assert the type has changed due to backing store enabling expect( parseNodeRegistry.contentTypeAssociatedFactories[streamContentType], - isA()); + isA(),); }); test('enableBackingStoreForParseNodeFactoryAlsoEnablesForDefaultInstance', @@ -94,7 +94,7 @@ void main() { expect( parseNodeRegistry.contentTypeAssociatedFactories[streamContentType] is BackingStoreParseNodeFactory, - isFalse); + isFalse,); // Act ApiClientBuilder.enableBackingStoreForParseNodeFactory(parseNodeRegistry); @@ -102,11 +102,11 @@ void main() { // Assert the type has changed due to backing store enabling for the default instance as well. expect( parseNodeRegistry.contentTypeAssociatedFactories[streamContentType], - isA()); + isA(),); expect( ParseNodeFactoryRegistry.defaultInstance .contentTypeAssociatedFactories[streamContentType], - isA()); + isA(),); }); test( 'enableBackingStoreForParseNodeFactoryAlsoEnablesForDefaultInstanceMultipleCallsDoesNotDoubleWrap', @@ -121,12 +121,12 @@ void main() { expect( parseNodeRegistry.contentTypeAssociatedFactories[streamContentType] is BackingStoreParseNodeFactory, - isFalse); + isFalse,); // Act final firstResult = ApiClientBuilder.enableBackingStoreForParseNodeFactory( - parseNodeRegistry); + parseNodeRegistry,); final secondResult = ApiClientBuilder.enableBackingStoreForParseNodeFactory(firstResult); final thirdResult = diff --git a/packages/kiota_http/lib/src/http_client_request_adapter.dart b/packages/kiota_http/lib/src/http_client_request_adapter.dart index f760f51..6e1af3b 100644 --- a/packages/kiota_http/lib/src/http_client_request_adapter.dart +++ b/packages/kiota_http/lib/src/http_client_request_adapter.dart @@ -297,7 +297,7 @@ class HttpClientRequestAdapter implements RequestAdapter { ApiClientBuilder.enableBackingStoreForParseNodeFactory(_pNodeFactory); _sWriterFactory = ApiClientBuilder.enableBackingStoreForSerializationWriterFactory( - _sWriterFactory); + _sWriterFactory,); BackingStoreFactorySingleton.instance = backingStoreFactory; } } diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart index d80c5b0..1dc89d3 100644 --- a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart +++ b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart @@ -57,7 +57,7 @@ void main() { 'someNull': const UntypedNull(), 'untypedArray': const UntypedArray(untypedNodesList), 'object': const UntypedObject( - {'name': UntypedString('a name'), 'age': UntypedInteger(8)}) + {'name': UntypedString('a name'), 'age': UntypedInteger(8)},), }; final writer = JsonSerializationWriter() diff --git a/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart b/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart index 5d5cb7c..117f3ff 100644 --- a/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart +++ b/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart @@ -57,7 +57,7 @@ class MultipartSerializationWriter implements SerializationWriter { @override void writeCollectionOfPrimitiveValues(String? key, Iterable? values) { throw UnsupportedError( - '$errorMessagePrefix collection of primitive values'); + '$errorMessagePrefix collection of primitive values',); } @override @@ -116,7 +116,7 @@ class MultipartSerializationWriter implements SerializationWriter { value.serialize(this); } else { throw Exception( - 'Expected MultipartBody instance but got ${value.runtimeType}'); + 'Expected MultipartBody instance but got ${value.runtimeType}',); } if (onAfterObjectSerialization != null) { onAfterObjectSerialization?.call(value); diff --git a/packages/kiota_serialization_multipart/test/test_entity.dart b/packages/kiota_serialization_multipart/test/test_entity.dart index 60d2dc8..8472ccb 100644 --- a/packages/kiota_serialization_multipart/test/test_entity.dart +++ b/packages/kiota_serialization_multipart/test/test_entity.dart @@ -33,7 +33,7 @@ class TestEntity implements Parsable, AdditionalDataHolder { 'workDuration': (node) => workDuration = node.getDurationValue(), 'startWorkTime': (node) => startWorkTime = node.getTimeOnlyValue(), 'endWorkTime': (node) => endWorkTime = node.getTimeOnlyValue(), - 'createdDateTime': (node) => createdDateTime = node.getDateTimeValue() + 'createdDateTime': (node) => createdDateTime = node.getDateTimeValue(), }; } From 77f2489c90b3c239ead519c99f21b3988411a519 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Thu, 14 Nov 2024 11:26:31 +0100 Subject: [PATCH 67/69] Formatting --- .../lib/src/api_client_builder.dart | 24 +++-- .../test/api_client_builder_test.dart | 89 +++++++++++-------- .../lib/src/http_client_request_adapter.dart | 3 +- .../test/json_serialization_writer_test.dart | 3 +- .../src/multipart_serialization_writer.dart | 6 +- 5 files changed, 76 insertions(+), 49 deletions(-) diff --git a/packages/kiota_abstractions/lib/src/api_client_builder.dart b/packages/kiota_abstractions/lib/src/api_client_builder.dart index f0f4738..11b0b44 100644 --- a/packages/kiota_abstractions/lib/src/api_client_builder.dart +++ b/packages/kiota_abstractions/lib/src/api_client_builder.dart @@ -26,14 +26,16 @@ class ApiClientBuilder { static SerializationWriterFactory enableBackingStoreForSerializationWriterFactory( - SerializationWriterFactory original,) { + SerializationWriterFactory original, + ) { var result = original; if (original is SerializationWriterFactoryRegistry) { _enableBackingStoreForSerializationRegistry(original); if (original != SerializationWriterFactoryRegistry.defaultInstance) { // if the registry is the default instance, we already enabled it above. No need to do it twice _enableBackingStoreForSerializationRegistry( - SerializationWriterFactoryRegistry.defaultInstance,); + SerializationWriterFactoryRegistry.defaultInstance, + ); } } if (result is BackingStoreSerializationWriterProxyFactory) { @@ -47,14 +49,16 @@ class ApiClientBuilder { } static ParseNodeFactory enableBackingStoreForParseNodeFactory( - ParseNodeFactory original,) { + ParseNodeFactory original, + ) { var result = original; if (original is ParseNodeFactoryRegistry) { _enableBackingStoreForParseNodeRegistry(original); if (original != ParseNodeFactoryRegistry.defaultInstance) { // if the registry is the default instance, we already enabled it above. No need to do it twice _enableBackingStoreForParseNodeRegistry( - ParseNodeFactoryRegistry.defaultInstance,); + ParseNodeFactoryRegistry.defaultInstance, + ); } } if (result is BackingStoreParseNodeFactory) { @@ -68,7 +72,8 @@ class ApiClientBuilder { } static void _enableBackingStoreForParseNodeRegistry( - ParseNodeFactoryRegistry registry,) { + ParseNodeFactoryRegistry registry, + ) { final keysToUpdate = []; registry.contentTypeAssociatedFactories.forEach((key, value) { if (value is! BackingStoreParseNodeFactory) { @@ -79,12 +84,14 @@ class ApiClientBuilder { keysToUpdate.forEach((key) { registry.contentTypeAssociatedFactories[key] = BackingStoreParseNodeFactory( - concrete: registry.contentTypeAssociatedFactories[key]!,); + concrete: registry.contentTypeAssociatedFactories[key]!, + ); }); } static void _enableBackingStoreForSerializationRegistry( - SerializationWriterFactoryRegistry registry,) { + SerializationWriterFactoryRegistry registry, + ) { final keysToUpdate = []; registry.contentTypeAssociatedFactories.forEach((key, value) { { @@ -97,7 +104,8 @@ class ApiClientBuilder { keysToUpdate.forEach((key) { registry.contentTypeAssociatedFactories[key] = BackingStoreSerializationWriterProxyFactory( - concrete: registry.contentTypeAssociatedFactories[key]!,); + concrete: registry.contentTypeAssociatedFactories[key]!, + ); }); } } diff --git a/packages/kiota_abstractions/test/api_client_builder_test.dart b/packages/kiota_abstractions/test/api_client_builder_test.dart index 1f20ae9..1401ed9 100644 --- a/packages/kiota_abstractions/test/api_client_builder_test.dart +++ b/packages/kiota_abstractions/test/api_client_builder_test.dart @@ -4,7 +4,8 @@ import 'package:test/test.dart'; import 'api_client_builder_test.mocks.dart'; @GenerateMocks( - [SerializationWriter, SerializationWriterFactory, ParseNodeFactory],) + [SerializationWriter, SerializationWriterFactory, ParseNodeFactory], +) void main() { const streamContentType = 'application/octet-stream'; @@ -16,20 +17,23 @@ void main() { .putIfAbsent(streamContentType, () => mockSerializationWriterFactory); expect( - serializationFactoryRegistry - .contentTypeAssociatedFactories[streamContentType] - is BackingStoreSerializationWriterProxyFactory, - isFalse,); + serializationFactoryRegistry + .contentTypeAssociatedFactories[streamContentType] + is BackingStoreSerializationWriterProxyFactory, + isFalse, + ); // Act ApiClientBuilder.enableBackingStoreForSerializationWriterFactory( - serializationFactoryRegistry,); + serializationFactoryRegistry, + ); // Assert the type has changed due to backing store enabling expect( - serializationFactoryRegistry - .contentTypeAssociatedFactories[streamContentType], - isA(),); + serializationFactoryRegistry + .contentTypeAssociatedFactories[streamContentType], + isA(), + ); }); test( 'enableBackingStoreForSerializationWriterFactoryAlsoEnablesForDefaultInstance', @@ -43,25 +47,29 @@ void main() { .putIfAbsent(streamContentType, () => mockSerializationWriterFactory); expect( - serializationFactoryRegistry - .contentTypeAssociatedFactories[streamContentType] - is BackingStoreSerializationWriterProxyFactory, - isFalse,); + serializationFactoryRegistry + .contentTypeAssociatedFactories[streamContentType] + is BackingStoreSerializationWriterProxyFactory, + isFalse, + ); // Act ApiClientBuilder.enableBackingStoreForSerializationWriterFactory( - serializationFactoryRegistry,); + serializationFactoryRegistry, + ); // Assert the type has changed due to backing store enabling expect( - serializationFactoryRegistry - .contentTypeAssociatedFactories[streamContentType], - isA(),); + serializationFactoryRegistry + .contentTypeAssociatedFactories[streamContentType], + isA(), + ); expect( - SerializationWriterFactoryRegistry.defaultInstance - .contentTypeAssociatedFactories[streamContentType], - isA(),); + SerializationWriterFactoryRegistry + .defaultInstance.contentTypeAssociatedFactories[streamContentType], + isA(), + ); }); test('enableBackingStoreForParseNodeFactory', () { final parseNodeRegistry = ParseNodeFactoryRegistry(); @@ -69,17 +77,19 @@ void main() { parseNodeRegistry.contentTypeAssociatedFactories .putIfAbsent(streamContentType, () => mockParseNodeFactory); expect( - parseNodeRegistry.contentTypeAssociatedFactories[streamContentType] - is BackingStoreParseNodeFactory, - isFalse,); + parseNodeRegistry.contentTypeAssociatedFactories[streamContentType] + is BackingStoreParseNodeFactory, + isFalse, + ); // Act ApiClientBuilder.enableBackingStoreForParseNodeFactory(parseNodeRegistry); // Assert the type has changed due to backing store enabling expect( - parseNodeRegistry.contentTypeAssociatedFactories[streamContentType], - isA(),); + parseNodeRegistry.contentTypeAssociatedFactories[streamContentType], + isA(), + ); }); test('enableBackingStoreForParseNodeFactoryAlsoEnablesForDefaultInstance', @@ -92,21 +102,24 @@ void main() { .putIfAbsent(streamContentType, () => mockParseNodeFactory); expect( - parseNodeRegistry.contentTypeAssociatedFactories[streamContentType] - is BackingStoreParseNodeFactory, - isFalse,); + parseNodeRegistry.contentTypeAssociatedFactories[streamContentType] + is BackingStoreParseNodeFactory, + isFalse, + ); // Act ApiClientBuilder.enableBackingStoreForParseNodeFactory(parseNodeRegistry); // Assert the type has changed due to backing store enabling for the default instance as well. expect( - parseNodeRegistry.contentTypeAssociatedFactories[streamContentType], - isA(),); + parseNodeRegistry.contentTypeAssociatedFactories[streamContentType], + isA(), + ); expect( - ParseNodeFactoryRegistry.defaultInstance - .contentTypeAssociatedFactories[streamContentType], - isA(),); + ParseNodeFactoryRegistry + .defaultInstance.contentTypeAssociatedFactories[streamContentType], + isA(), + ); }); test( 'enableBackingStoreForParseNodeFactoryAlsoEnablesForDefaultInstanceMultipleCallsDoesNotDoubleWrap', @@ -119,14 +132,16 @@ void main() { .putIfAbsent(streamContentType, () => mockParseNodeFactory); expect( - parseNodeRegistry.contentTypeAssociatedFactories[streamContentType] - is BackingStoreParseNodeFactory, - isFalse,); + parseNodeRegistry.contentTypeAssociatedFactories[streamContentType] + is BackingStoreParseNodeFactory, + isFalse, + ); // Act final firstResult = ApiClientBuilder.enableBackingStoreForParseNodeFactory( - parseNodeRegistry,); + parseNodeRegistry, + ); final secondResult = ApiClientBuilder.enableBackingStoreForParseNodeFactory(firstResult); final thirdResult = diff --git a/packages/kiota_http/lib/src/http_client_request_adapter.dart b/packages/kiota_http/lib/src/http_client_request_adapter.dart index 6e1af3b..82a549c 100644 --- a/packages/kiota_http/lib/src/http_client_request_adapter.dart +++ b/packages/kiota_http/lib/src/http_client_request_adapter.dart @@ -297,7 +297,8 @@ class HttpClientRequestAdapter implements RequestAdapter { ApiClientBuilder.enableBackingStoreForParseNodeFactory(_pNodeFactory); _sWriterFactory = ApiClientBuilder.enableBackingStoreForSerializationWriterFactory( - _sWriterFactory,); + _sWriterFactory, + ); BackingStoreFactorySingleton.instance = backingStoreFactory; } } diff --git a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart index 1dc89d3..249a955 100644 --- a/packages/kiota_serialization_json/test/json_serialization_writer_test.dart +++ b/packages/kiota_serialization_json/test/json_serialization_writer_test.dart @@ -57,7 +57,8 @@ void main() { 'someNull': const UntypedNull(), 'untypedArray': const UntypedArray(untypedNodesList), 'object': const UntypedObject( - {'name': UntypedString('a name'), 'age': UntypedInteger(8)},), + {'name': UntypedString('a name'), 'age': UntypedInteger(8)}, + ), }; final writer = JsonSerializationWriter() diff --git a/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart b/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart index 117f3ff..78c6ed9 100644 --- a/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart +++ b/packages/kiota_serialization_multipart/lib/src/multipart_serialization_writer.dart @@ -57,7 +57,8 @@ class MultipartSerializationWriter implements SerializationWriter { @override void writeCollectionOfPrimitiveValues(String? key, Iterable? values) { throw UnsupportedError( - '$errorMessagePrefix collection of primitive values',); + '$errorMessagePrefix collection of primitive values', + ); } @override @@ -116,7 +117,8 @@ class MultipartSerializationWriter implements SerializationWriter { value.serialize(this); } else { throw Exception( - 'Expected MultipartBody instance but got ${value.runtimeType}',); + 'Expected MultipartBody instance but got ${value.runtimeType}', + ); } if (onAfterObjectSerialization != null) { onAfterObjectSerialization?.call(value); From e8f74f4b689415ea8517835e523aad7e6dcf0821 Mon Sep 17 00:00:00 2001 From: Kees-Schotanus Date: Fri, 15 Nov 2024 06:53:13 +0100 Subject: [PATCH 68/69] Added multipart serialization to makefile --- Makefile | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index aecc558..d88225c 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -pub-get: pub-get-abstractions pub-get-http pub-get-serialization-text pub-get-serialization-form pub-get-serialization-json +pub-get: pub-get-abstractions pub-get-http pub-get-serialization-text pub-get-serialization-form pub-get-serialization-json pub-get-serialization-multipart pub-get-abstractions: cd packages/kiota_abstractions && dart pub get @@ -15,6 +15,9 @@ pub-get-serialization-form: pub-get-serialization-json: cd packages/kiota_serialization_json && dart pub get +pub-get-serialization-multipart: + cd packages/kiota_serialization_multipart && dart pub get + format: dart format packages @@ -32,7 +35,10 @@ generate-serialization-form: generate-serialization-json: cd packages/kiota_serialization_json && dart run build_runner build --delete-conflicting-outputs -test: test-abstractions test-http test-serialization-text test-serialization-form test-serialization-json +generate-serialization-multipart: + cd packages/kiota_serialization_multipart && dart run build_runner build --delete-conflicting-outputs + +test: test-abstractions test-http test-serialization-text test-serialization-form test-serialization-json test-serialization-multipart test-abstractions: pub-get-abstractions generate-abstractions cd packages/kiota_abstractions && dart test @@ -47,4 +53,7 @@ test-serialization-form: pub-get-serialization-form generate-serialization-form cd packages/kiota_serialization_form && dart test test-serialization-json: pub-get-serialization-json generate-serialization-json - cd packages/kiota_serialization_json && dart test \ No newline at end of file + cd packages/kiota_serialization_json && dart test + +test-serialization-multipart: pub-get-serialization-multipart generate-serialization-multipart + cd packages/kiota_serialization_multipart && dart test \ No newline at end of file From 283ea4b5b033e18b8756846f9254d6629c3221e5 Mon Sep 17 00:00:00 2001 From: Joanne ter Maat Date: Fri, 15 Nov 2024 07:26:39 +0100 Subject: [PATCH 69/69] Fixed warnings --- .../lib/src/json_serialization_writer.dart | 2 +- packages/kiota_serialization_multipart/test/test_entity.dart | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart index 17f0551..7834466 100644 --- a/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart +++ b/packages/kiota_serialization_json/lib/src/json_serialization_writer.dart @@ -86,7 +86,7 @@ class JsonSerializationWriter implements SerializationWriter { } else { final originalContents = {..._contents}; _contents.clear(); - final List> objects = []; + final objects = >[]; for (final value in values) { value.serialize(this); objects.add({..._contents}); diff --git a/packages/kiota_serialization_multipart/test/test_entity.dart b/packages/kiota_serialization_multipart/test/test_entity.dart index 8472ccb..503ff7a 100644 --- a/packages/kiota_serialization_multipart/test/test_entity.dart +++ b/packages/kiota_serialization_multipart/test/test_entity.dart @@ -50,8 +50,4 @@ class TestEntity implements Parsable, AdditionalDataHolder { ..writeCollectionOfPrimitiveValues('deviceNames', deviceNames) ..writeAdditionalData(additionalData); } - - static TestEntity createFromDiscriminatorValue(ParseNode parseNode) { - return TestEntity(); - } }