1

I'm trying to create Dart classes for FHIR resources defined in Json. The full Json schema for FHIR is here if anyone wants to look. My issue is with a oneOf declaration. Specifically, I have a class like the following (I'm not including the full class definition here, although I can if anyone thinks it would be helpful):

class Bundle_Entry {
  Resource resource;

Bundle_Entry(this.resource});

  factory Bundle_Entry.fromJson(Map<String, dynamic> json) => _$Bundle_EntryFromJson(json);
  Map<String, dynamic> toJson() => _$Bundle_EntryToJson(this);
} 

My problem is that ResourceList is defined as oneOf a number of other classes.

"ResourceList": {
  "oneOf": [
    { "$ref": "#/definitions/Account" },
    { "$ref": "#/definitions/ActivityDefinition" },
    ...
  ]
}

I've tried declaring the 'resource' variable as types 'var', 'dynamic', and 'ResourceList' and created a class ResourceList that just contains a resource.

Each resource has a field titled 'resourceType', so I've also tried creating a ResourceList function that returns different types based on argument of 'resourceType', which also doesn't work.

If I do an http request, the actual response I'm trying to parse looks like this:

{
  "resourceType": "Bundle",
  "type": "searchset",
  "entry": [
      {
          "resource": {
              "name": "Jaba the Hutt"
              "birthDate": "1980-07-27",
              "id": "b26646dd-c549-4981-834e-bb4145d104b8",
              "resourceType": "Patient"
           }
      }
    ]
}

Any suggestions would be appreciated.

Updating my question. It's interesting, that the first answer is similar to what I've come up with currently.

class Bundle_Entry {
  dynamic resource;
  Bundle_Entry({this.resource});

  Bundle_Entry.fromJson(Map<String, dynamic> json) =>
      Bundle_Entry(
        resource: json['resource'] == null
        ? null
        : ResourceTypes(
            json['resource']['resourceType'], json['resource'] as Map<String, dynamic>)
);}

  Map<String, dynamic> toJson() => _$Bundle_EntryToJson(this);
}

dynamic ResourceTypes(String type, Map<String, dynamic> json) {
  if (type == 'Element') return (new Element.fromJson(json));
  if (type == 'Extension') return (new Extension.fromJson(json));
  if (type == 'Patient') return (new Narrative.fromJson(json));

My issue is that then I have to hard code each ResourceType, and it seemed like there should be an easier way.

Grey
  • 331
  • 3
  • 11

2 Answers2

1

I have been trying to build a similar thing. I approached it using inheritance and created a function to return the resource based on the ResourceType field.

Resource getResource(json) {
  if(json == null) return null;
  if(json["resourceType"] == "Patient") return Patient.fromJson(json);
  if(json["resourceType"]=="Procedure") return Procedure.fromJson(json);
  if(json["resourceType"]=="Encounter") return Encounter.fromJson(json);
  if(json["resourceType"]=="Appointment") return Appointment.fromJson(json);
  if(json["resourceType"]=="Slot") return Slot.fromJson(json);
  if(json["resourceType"]=="Slot") return Slot.fromJson(json);
  if(json["resourceType"]=="Observation") return Observation.fromJson(json);
  if(json["resourceType"]=="Condition") return Condition.fromJson(json);
  if(json["resourceType"]=="DiagnosticReport") return DiagnosticReport.fromJson(json);
  if(json["resourceType"]=="MedicationRequest") return MedicationRequest.fromJson(json);
  if(json["resourceType"]=="CarePlan") return CarePlan.fromJson(json);
  if(json["resourceType"]=="Practitioner") return Practitioner.fromJson(json);
  if(json["resourceType"]=="AllergyIntolerance") return AllergyIntolerance.fromJson(json);

  return Resource.fromJson(json);
}

Where Patient, Procedure, etc. are subclasses of Resource:

class Entry {
  String fullUrl;
  Resource resource;

  factory Entry.fromJson(Map<String, dynamic> json) => Entry(
        fullUrl: json["fullUrl"] == null ? null : json["fullUrl"],

        //This line is the magic
        resource: getResource(json["resource"]),
        search: json["search"] == null ? null : Search.fromJson(json["search"]),
        response: json["response"] == null
            ? null
            : Response.fromJson(json["response"]),
      );

Rich
  • 26
  • 3
  • Since you're suggesting this as an answer, please provide the full code. Answers need to provide a workable answer to the question – flen Feb 24 '20 at 18:47
  • I updated the post. Let me know if there's more you want me to add. – Rich Mar 02 '20 at 03:15
0

While not ideal, I did end up using the answer above, just modified slightly.

Resource _resourceFromJson(Map<String, dynamic> json) {
  final dynamic resourceType = json['resourceType'];
  switch (resourceType) {
    case 'Account':
      return Account.fromJson(json);
    case 'ActivityDefinition':
      return ActivityDefinition.fromJson(json);
    case 'AdministrableProductDefinition':
      return AdministrableProductDefinition.fromJson(json);
    case 'AdverseEvent':
      return AdverseEvent.fromJson(json);
    case 'AllergyIntolerance':
      return AllergyIntolerance.fromJson(json);
    ...

For anyone who runs into this. Full file is here

Grey
  • 331
  • 3
  • 11