New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Serialization Issues #873
Comments
So I thought I'd update this. Since I couldn't get the above working, I've decided to try a different tack. Ideally it would just be generated from the classes I already have, but since I can't get that to work, I thought I'd try and pull the data from the class directly into the yaml file for generation. I'm still working out some of the details, but I think it general it's a possibility. I'll attach my script here in case anyone else wants to try and play with it: import 'dart:io';
Future<void> main() async {
final Directory dir = Directory('.');
final List<String> fileList = await dir
.list(recursive: true)
.map((FileSystemEntity event) => event.path)
.toList();
for (final String file in fileList) {
if (file.contains('.dart') &&
!file.contains('.g.') &&
!file.contains('freezed') &&
!file.contains('enum')) {
final String fileString = await File(file).readAsString();
final List<String> stringList = fileString.split('\n');
String yaml = '';
bool isClass = false;
String className = '';
for (final String line in stringList) {
if (isClass) {
if (line.trim().startsWith('///')) {
} else if (line.endsWith(',')) {
final List<String> splitLine = line.split(' ');
yaml += ' ';
yaml += changeFieldName(splitLine.last.replaceAll(',', ''));
yaml += ': ';
if (changeFieldName(splitLine.last.replaceAll(',', '')) ==
'routeOfAdministration' &&
className == 'AdministrableProductDefinition') {
yaml += 'AdministrableProductDefinitionRouteOfAdministration';
} else if (changeFieldName(splitLine.last.replaceAll(',', '')) ==
'relatedMedicationKnowledge' &&
className == 'MedicationKnowledge') {
yaml += 'MedicationKnowledgeRelatedMedicationKnowledge';
} else {
yaml += changeYamlTypes(splitLine[splitLine.length - 2]);
}
yaml += '\n';
} else if (line.contains('}) = _')) {
isClass = false;
await File(
'../../../fhirpod/fhirpod_server/lib/src/protocol/${className.toLowerCase()}.yaml')
.writeAsString(yaml);
yaml = '';
}
}
if (line.contains('factory') && line.contains('({')) {
isClass = true;
className =
line.replaceAll('factory ', '').replaceAll('({', '').trim();
yaml += 'class: $className\n';
yaml += 'fields: \n';
}
}
}
}
await File('../../../fhirpod/fhirpod_server/lib/src/protocol/resource.yaml')
.writeAsString(resourceYaml);
}
const String resourceYaml = '''
class: Resource
fields:
resourceType: String
id: String?
meta: FhirMeta?
implicitRules: String?
implicitRulesElement: Element?
language: String?
languageElement: Element?
text: Narrative?
contained: List<Resource>?
extension_: List<FhirExtension>?
modifierExtension: List<FhirExtension>?
''';
String changeYamlTypes(String oldType) {
final int index = yamlTypes.keys.toList().indexWhere((String element) =>
element.contains(oldType
.replaceAll('?', '')
.replaceAll('List<', '')
.replaceAll('>', '')));
if (index == -1) {
return oldType;
} else {
return oldType.replaceAll(
yamlTypes.keys.elementAt(index), yamlTypes.values.elementAt(index));
}
}
String changeFieldName(String name) => name
.replaceAll('productionIdentifierInUDI', 'productionIdentifierInUdi')
.replaceAll('carrierAIDC', 'carrierAidc')
.replaceAll('carrierHRF', 'carrierHrf')
.replaceAll('requestURL', 'requestUrl');
const Map<String, String> yamlTypes = <String, String>{
'R5ResourceType': 'String',
'String': 'String',
'FhirBase64Binary': 'String',
'FhirBoolean': 'bool',
'FhirCanonical': 'String',
'FhirCode': 'String',
'FhirDate': 'DateTime',
'FhirTime': 'String',
'FhirDateTime': 'DateTime',
'FhirDecimal': 'double',
'FhirUri': 'String',
'FhirUrl': 'String',
'FhirId': 'String',
'FhirInstant': 'DateTime',
'FhirInteger': 'int',
'FhirInteger64': 'BigInt',
'FhirMarkdown': 'String',
'FhirOid': 'String',
'FhirPositiveInt': 'int',
'FhirUnsignedInt': 'int',
'FhirUuid': 'String',
'FhirDuration': 'String',
'IdentifierUse': 'String',
'QuantityComparator': 'String',
'DurationComparator': 'String',
'DistanceComparator': 'String',
'CountComparator': 'String',
'AgeComparator': 'String',
'HumanNameUse': 'String',
'AddressUse': 'String',
'AddressType': 'String',
'ContactPointSystem': 'String',
'ContactPointUse': 'String',
'TimingRepeatDurationUnit': 'String',
'TimingRepeatPeriodUnit': 'String',
'TimingRepeatWhen': 'String',
'ContributorType': 'String',
'DataRequirementSortDirection': 'String',
'RelatedArtifactType': 'String',
'TriggerDefinitionType': 'String',
'NarrativeStatus': 'String',
'ElementDefinitionRepresentation': 'String',
'ElementDefinitionSlicingRules': 'String',
'ElementDefinitionDiscriminatorType': 'String',
'ElementDefinitionTypeAggregation': 'String',
'ElementDefinitionTypeVersioning': 'String',
'ElementDefinitionConstraintSeverity': 'String',
'ElementDefinitionBindingStrength': 'String',
}; |
So some progress today, albeit with a different direction. Or at least, a workaround. First step is to generate all of your code as usual using freezed and jsonserializable. Then, add in the SerializationManager as an optional, positional parameter (this way it doesn't interfere if you call fromJson from any other methods or functions). I did a regex lookup and replace in VSCode. End result looks like this: // ignore_for_file: invalid_annotation_target
// ignore_for_file: sort_unnamed_constructors_first
// ignore_for_file: sort_constructors_first
// ignore_for_file: avoid_unused_constructor_parameters
// Dart imports:
import 'dart:convert';
// Package imports:
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:serverpod_serialization/serverpod_serialization.dart';
import 'package:yaml/yaml.dart';
// Project imports:
import '../../r5.dart';
part 'element.freezed.dart';
part 'element.g.dart';
@freezed
class Element with _$Element {
Element._();
factory Element({
@JsonKey(name: 'id') FhirId? fhirId,
@JsonKey(name: 'extension') List<FhirExtension>? extension_,
@JsonKey(name: 'fhir_comments') List<String>? fhirComments,
}) = _Element;
factory Element.fromJson(
Map<String, dynamic> json, [
SerializationManager? serializationManager,
]) =>
_$ElementFromJson(json);
}
} Again, you can't regenerate your code at this point, it will throw an error. But, you can generate serverpod data. In your type: server
client_package_path: ../fhirpod_client
extraClasses:
- package:fhir/r5.dart:Element Then run |
Describe the bug
I'm having trouble using the serialization process for serverpod. Here's the repo if you'd like to take a look: https://github.com/fhir-fli/fhirpod. All of my classes are freezed, and I've adjusted all of the fromJson to include the serializationManagers. That has no errors. When I try to generate code, if I remove json_serializable from the pubspec and all of the part 'file.g.dart'; code, then it generates fine. However, it doesn't generate the toJson() files that are required.
However, when I do include the json_serializable to generate the toJson() methods, I get this error message:
I'm using serverpod_serialization: ^1.1.0.
Just hoping someone else had a similar experience and had found a solution.
The text was updated successfully, but these errors were encountered: