New To FHIR: how to convert my data into fhir Format

I am new to fhir. i have deployed fhir Server using hapi jpa fhir Server.
I played around with it . i know to create ,update or get Patient using rest apis in fhir Server

But my Question is how to convert my data to fhir Format,
i have lot of Patient data stored in MySQL databases now how to convert this data to fhir Format.
i read somewhere we should do mapping.
please guide me About fhir and fhir mapping.
How to do… where start off…
i am struggling from past 2 weeks learning fhir

1 Like

Hello @luffy,

If you are asking “How to map your database data to Patient FHIR structure” you can take a look at Patient resource details (“https://www.hl7.org/fhir/patient.html”). It gives you plenty of information about “What” should be considered a Patient resource and “How” to interpret it.
It also shows how to map Patients to other well-know formats and structures on clinical documents (https://www.hl7.org/fhir/patient-mappings.html).

If you are asking “How to persist Patient, and other resources, structures” you can use a lot of technologies. SQL, NoSQL, JSON Databases (as MongoDB), JPA… Take a look at (https://www.health-samurai.io/fhirbase). It is a framework who implements a lot of helpful procedures.

One approach to convert data is to implement Adapters (https://en.wikipedia.org/wiki/Adapter_pattern), from your MySQL database structure to the Patient FHIR structure. Example:

  • MyPatient.name -> Patient.name[0].text
  • DateFormat(MyPatient.birthdate) -> Patient.birthDate
  • And so on…

FHIR is a standard for health care data exchange, it needs to cover plenty of use cases along with a huge variety of clinical standards. You should identify your needs.

Also, take a look at Extensions (https://www.hl7.org/fhir/extensibility.html). It helps you to cover attributes non-canonicals to FHIR structure.

I could not 100% understand your question, so I wish I could help you.

1 Like

Thanks for the Reply.

I have read this links “https://www.hl7.org/fhir/patient.html”) & (https://www.hl7.org/fhir/patient-mappings.html). But still i am unable to understand how to start writing a mapper or to map data.

I will explain what i want. Please guide me. or give me examples
For example :
I have a mysql database such as patdb containing tables as pat, obs, therpie etc
Pat table has fields such

No FirstName lastName Birthday sex street City patid …
1 Tom fisher 12.03.1948 m indiranager bangalore 2345
2 Angel Merry 20.02.2020 f kodialli Delhi 3456
3 Ambi Henry 18.12.1948 f Airport road mumbai 1234
… so on

and table therpie has

ID Therapiebeginndate therapieenddate Therapie Intention
2354 12.02.2014 22.05.2019 Palliativ
3456 01.02.1989 15.07.2000 Chemotherapie

so on

I have huge amount of data.

Now how to convert this data in fhir Format and send it to fhir Server
I already have Server. But now i am not understanding how to convert this Kind of data to fhir Format.
I want this data in fhir Format.

Kindly please give example.

1 Like

You’re going to have to write code - in Java, C# or some other language that will perform the translation. Your database is unique. There’s no off-the-shelf solution that will magically do the conversion for you. (Also, please don’t raise the same question both here and on chat.fhir.org at the same time.)

1 Like

Ya I know I should write code. I’m writing to in java. I just wanted a small example with small data… Maybe a few lines of java code for abovd data or just for 2 rows from above. . I asked because I’m very new and I want to know if what I am doing is right.I am learning.

About posting in chat. I never got response thier so I posted here. Communities are thier to help. So what wrong in posting twice.

Anyways thanks for your reply. I won’t post same.

The general guideline is to give a business day or two for responses in one place before asking elsewhere. Having the same thing asked in multiple places creates extra work for community members and may result in the discussion happening in multiple places - which makes it harder to keep track of all of the advice being given and ensuring a consistent message. Full guidelines for asking questions are documented here: https://confluence.hl7.org/display/FHIR/FHIR+Rules+for+Asking+Questions

Hi @luffy

Some pointers for a design which we used successfully:

  1. Pull required FHIR resources in a individual files (you may have to pull all required resources if you want to enforce referential integrity.

  2. Create mapping files (you can annotate schema or pull in other meta data files).

  3. Write an algorithm to walk thru each record, read mapping file and schema, generate an object (JSON preferably) as per the schema.

Hope it helps.

Thank you,

Hi @anil

Thanks for your response. Can you please share a sample of a mapping file and sample code on how you generated the json for e.g. for a patient resource?

Libraries such as https://github.com/FirelyTeam/fhir-net-api may help.
Try to find some library which contains models, read the FHIR documentation to determine resource-to-resource, firld-to-field relations and write stupid simple code for mappings.

@naitik, sharing a sample mapping file for Person (relatively simple resource). Some highlights:

  1. You will notice it is the same as the FHIR schema (simplified by removing not needed attributes).
  2. There are a few additional attributes:
    a) op - transformation to be performed.
    b) source / value - the attribute of input data or an expression.
    c) codeMapping - mappings of input codes onto corresponding FHIR codes.
  3. op can be one of the following:
    a) value - another attribute called “value” gives the hard code value. This is useful for certain constants.
    b) “=” - simple assignment (take the value of the source as it is)
    c) “exp” - Evaluate given expression against the input data.
    d) “template” - replace template varaibles with the value in the input data.
    e) “script” - execute a script (rule) against input data.
    f) dateFormat - requires additional input for input datec format and outpur date format.

The rest is self-explanatory. We built a UI tool for creating mapping with the right side being the FHIR resources, the left side being the input data.

{
“orgName”: “ABCCorp”,
“flowsByName”: {
“Person”: {
“name”: “Person”,
“associatedObj”: {
“resourceName”: “Person”,
“name”: “Person”
},
“activities”: [
{
“name”: “id”,
“type”: “string”,
“description”: “The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.”,
“value”: “$UUID”,
“min”: 0,
“max”: “1”,
“lvl”: 0,
“qualifiedName”: “id”,
“op”: “value”
},
{
“name”: “use”,
“description”: “The purpose of this identifier.”,
“type”: “string”,
“value”: “usual”,
“enum”: [
“usual”,
“official”,
“temp”,
“secondary”,
“old”
],
“isEnum”: true,
“lvl”: 1,
“qualifiedName”: “identifier[].use”,
“op”: “value”
},
{
“name”: “type”,
“type”: “string”,
“description”: “A coded type for the identifier that can be used to determine which identifier to use for a specific purpose.”,
“codingSystem”: “http://ABCCorp.com/CodeSystem/v1-0101”,
“isEnum”: true,
“isCodableConcept”: true,
“lvl”: 1,
“qualifiedName”: “identifier[].type”,
“op”: “=”
},
{
“name”: “system”,
“description”: “Establishes the namespace for the value - that is, a URL that describes a set values that are unique.”,
“type”: “string”,
“value”: “$orgUUID”,
“lvl”: 1,
“qualifiedName”: “identifier[].system”,
“op”: “value”
},
{
“name”: “value”,
“type”: “string”,
“description”: “The portion of the identifier typically relevant to the user and which is unique within the context of the system.”,
“lvl”: 1,
“qualifiedName”: “identifier[].value”,
“op”: “=”,
“source”: “person_id”
},
{
“name”: “family”,
“description”: “The part of a name that links to the genealogy. In some cultures (e.g. Eritrea) the family name of a son is the first name of his father.”,
“type”: “string”,
“lvl”: 1,
“qualifiedName”: “name[].family”,
“op”: “=”,
“source”: “last_name”
},
{
“name”: “given”,
“description”: “Given name.”,
“type”: “string”,
“isArray”: true,
“index”: 0,
“lvl”: 1,
“qualifiedName”: “name[].given[]”,
“op”: “concate”,
“source”: “first_name + middle_name”
},
{
“name”: “prefix”,
“description”: “Part of the name that is acquired as a title due to academic, legal, employment or nobility status, etc. and that appears at the start of the name.”,
“type”: “string”,
“isArray”: true,
“index”: 0,
“lvl”: 1,
“qualifiedName”: “name[].prefix[]”,
“op”: “=”,
“source”: “prefix_name”
},
{
“name”: “suffix”,
“description”: “Part of the name that is acquired as a title due to academic, legal, employment or nobility status, etc. and that appears at the end of the name.”,
“type”: “string”,
“isArray”: true,
“index”: 0,
“lvl”: 1,
“qualifiedName”: “name[].suffix[]”,
“op”: “=”,
“source”: “suffix_name”
},
{
“name”: “gender”,
“description”: “Administrative Gender.”,
“type”: “string”,
“enum”: [
“male”,
“female”,
“other”,
“unknown”
],
“isEnum”: true,
“min”: 0,
“max”: “1”,
“lvl”: 0,
“qualifiedName”: “gender”,
“op”: “=”,
“source”: “sex”
},
{
“name”: “birthDate”,
“type”: “date”,
“description”: “The birth date for the person.”,
“min”: 0,
“max”: “1”,
“lvl”: 0,
“qualifiedName”: “birthDate”,
“op”: “=”
},
{
“name”: “line”,
“description”: “This component contains the house number, apartment number, street name, street direction, P.O. Box number, delivery hints, and similar address information.”,
“type”: “string”,
“isArray”: true,
“index”: 0,
“lvl”: 1,
“qualifiedName”: “address[].line[]”,
“op”: “concate”,
“source”: “address_line_1 + address_line_2”
},
{
“name”: “city”,
“description”: “The name of the city, town, suburb, village or other community or delivery center.”,
“type”: “string”,
“lvl”: 1,
“qualifiedName”: “address[].city”,
“op”: “=”,
“source”: “city”
},
{
“name”: “state”,
“description”: “Sub-unit of a country with limited sovereignty in a federally organized country. A code may be used if codes are in common use (e.g. US 2 letter state codes).”,
“type”: “string”,
“lvl”: 1,
“qualifiedName”: “address[].state”,
“op”: “=”,
“source”: “state”
},
{
“name”: “postalCode”,
“description”: “A postal code designating a region defined by the postal service.”,
“type”: “string”,
“lvl”: 1,
“qualifiedName”: “address[].postalCode”,
“op”: “=”,
“source”: “zip”
},
{
“name”: “active”,
“type”: “boolean”,
“description”: “Whether this person’s record is in active use.”,
“value”: true,
“min”: 0,
“max”: “1”,
“lvl”: 0,
“qualifiedName”: “active”,
“op”: “value”
},
{
“name”: “notes”,
“description”: “Custom extension for storing information as text.”,
“isExtension”: true,
“type”: “string”,
“lvl”: 0,
“qualifiedName”: “notes”,
“op”: “template”,
“source” : “{{{}}}”
}
],
“selectedActivityName”: “identifier[].value”,
}
}
}