hl7v2_parser 0.1.0 copy "hl7v2_parser: ^0.1.0" to clipboard
hl7v2_parser: ^0.1.0 copied to clipboard

Parse, generate, and access HL7v2 messages in Dart. Lazy parser, typed segment extensions, Terser path access, ACK/NAK generation. Zero dependencies, all platforms.

hl7v2_parser #

Pub Version Build Status License: BSD-3-Clause

Parse, generate, and access HL7v2 messages in pure Dart.

The first comprehensive HL7v2 library for Dart and Flutter. Zero dependencies, all platforms (web, mobile, server). Lazy parser that handles 490K+ messages per second.

No more Python/Java sidecars. If your Flutter app talks to hospital systems (LIS, RIS, analyzers, EMRs), this package gives you native HL7v2 support.

Quick Start #

# pubspec.yaml
dependencies:
  hl7v2_parser: ^0.1.0
import 'package:hl7v2_parser/hl7v2_parser.dart';

final raw = 'MSH|^~\\&|LAB|HOSP|EMR|HOSP|20240101120000||ORU^R01|MSG001|P|2.5\r'
    'PID|||12345^^^HOSP^MR||DOE^JOHN^A||19800101|M\r'
    'OBX|1|NM|WBC^White Blood Cell||7.2|10*3/uL|4.5-11.0|N|||F\r';

final message = Message.parse(raw);

// Index access
print(message.segment('PID')!.field(5).first.value); // DOE^JOHN^A

// Terser path access
print(message.get('PID-5-2')); // JOHN

// Typed segment access
print(message.pid!.patientName); // DOE^JOHN^A (XpnValue)
print(message.pid!.patientName!.givenName); // JOHN

Features #

Parse any HL7v2 message #

Lazy parser — segments are split upfront, fields/components parsed on first access. Custom delimiters and encoding characters are fully supported.

final message = Message.parse(raw);
print(message.messageType);    // ORU
print(message.triggerEvent);   // R01
print(message.version);        // 2.5
print(message.segments.length); // 3

Three ways to access data #

1. Index-based — direct positional access, fastest for known field numbers:

final pid = message.segment('PID')!;
final name = pid.field(5).first.component(1).value; // Family name

2. Terser path — string-based path like PID-5-2, familiar to HL7 developers:

final givenName = message.get('PID-5-2');    // JOHN
message.set('PID-5-2', 'JANE');              // Modify in place

3. Typed segment extensions — named getters with composite data types:

final pid = message.pid!;
print(pid.patientName!.familyName);   // DOE
print(pid.patientName!.givenName);    // JOHN
print(pid.dateOfBirth);               // 19800101
print(pid.administrativeSex);         // M

Generate HL7v2 wire format #

Round-trip fidelity: Message.parse(raw).encode() == normalize(raw) for all tested messages. Trailing empty fields are stripped at every level.

final encoded = message.encode();
// MSH|^~\&|LAB|HOSP|EMR|HOSP|20240101120000||ORU^R01|MSG001|P|2.5\r...

Build messages from scratch #

Fluent builder API with automatic MSH-7 (timestamp) and MSH-10 (control ID) generation.

final msg = MessageBuilder()
    .msh((b) => b
        .sendingApplication('LAB')
        .sendingFacility('HOSP')
        .receivingApplication('EMR')
        .receivingFacility('HOSP')
        .messageType('ORU', 'R01')
        .version('2.5'))
    .addSegment('PID', (b) => b
        .field(3, '12345^^^HOSP^MR')
        .field(5, 'DOE^JOHN^A')
        .field(7, '19800101')
        .field(8, 'M'))
    .addSegment('OBX', (b) => b
        .field(1, '1')
        .field(2, 'NM')
        .field(3, 'WBC^White Blood Cell')
        .field(5, '7.2')
        .field(6, '10*3/uL')
        .field(7, '4.5-11.0')
        .field(8, 'N')
        .field(11, 'F'))
    .build();

ACK/NAK generation #

Generate acknowledgement messages per HL7v2 spec. Supports both original mode (AA/AE/AR) and enhanced mode (CA/CE/CR).

final ack = message.generateAck(code: AckCode.aa);
print(ack.get('MSA-1')); // AA
print(ack.get('MSA-2')); // MSG001 (echoes original control ID)

// Rejection with error message
final nak = message.generateAck(
    code: AckCode.ar,
    errorMessage: 'Unknown patient ID',
);

Structural validation #

Validate messages against segment definitions — required fields, data types, max lengths, unknown segments.

final errors = message.validate();
for (final error in errors) {
  print('${error.severity}: ${error.message} '
      '(${error.segment}:${error.fieldNumber})');
}

Escape handling #

Full HL7v2 escape sequence support including \F\, \S\, \R\, \E\, \T\, hex (\Xhh\), and custom-delimiter escapes. Automatic unescape on read, escape on write.

// Raw value preserves escapes, .value unescapes
final raw = pid.field(5).first.rawValue;   // Smith\T\Jones
final val = pid.field(5).first.value;      // Smith&Jones

25 typed segment extensions #

Named getters for commonly used segments. Composite data types (XPN, CWE, CX, XAD, etc.) are returned as typed objects with named component access.

Segment Description
MSH Message Header
PID Patient Identification
PV1 Patient Visit
OBR Observation Request
OBX Observation/Result
ORC Common Order
MSA Message Acknowledgement
EVN Event Type
ERR Error
NK1 Next of Kin
AL1 Allergy Information
DG1 Diagnosis
FT1 Financial Transaction
GT1 Guarantor
IAM Patient Adverse Reaction
IN1 Insurance
MRG Merge Patient Information
NTE Notes and Comments
PD1 Patient Additional Demographics
ROL Role
RXA Pharmacy/Treatment Administration
RXO Pharmacy/Treatment Order
SCH Scheduling Activity Information
SPM Specimen
TXA Transcription Document Header

Z-segments parse transparently — access their fields by index or Terser path.

16 composite data types #

XpnValue, CweValue, CxValue, XadValue, XcnValue, XtnValue, HdValue, EiValue, PlValue, PtValue, VidValue, MsgValue, CqValue, ErlValue, FcValue, SnValue — all with named component getters and automatic unescaping.

Benchmarks #

Measured on Apple M-series, Dart 3.8.1 (stable), macOS. Each benchmark runs for ≥3 seconds after 100 warmup iterations.

Benchmark msg/s avg latency
Parse ADT^A01 (6 segments) 493,908 2.0 µs
Parse ORM^O01 (7 segments) 508,266 2.0 µs
Parse ORU^R01 (11 segments) 442,369 2.3 µs
Parse Large ORU (55 segments) 80,878 12.4 µs
Round-trip ADT^A01 34,925 28.6 µs
Round-trip ORU^R01 30,859 32.4 µs
Terser 10-path lookup 165,333 6.0 µs

Platform Support #

Platform hl7v2 hl7v2_mllp
Dart VM (server) Yes Yes
Flutter (Android/iOS) Yes Yes
Flutter Web Yes No*
Dart CLI Yes Yes

* hl7v2_mllp requires dart:io for TCP sockets. Core parsing works everywhere.

MLLP Transport #

For TCP transport over MLLP (client, server, TLS, reconnection), see the companion package hl7v2_mllp.

Comparison #

Feature hl7v2 hl7_v2 v0.0.1
Parse ER7 Yes Yes
Generate ER7 Yes No
Terser paths Yes No
Typed segments 25 0
Composite types 16 0
ACK/NAK generation Yes No
Message builder Yes No
Validation Yes No
Escape sequences Full Partial
Custom delimiters Yes No
MLLP transport Separate pkg No
Zero dependencies Yes No
Web platform Yes No
Benchmark (msg/s) 490K+

Contributing #

Contributions welcome! Areas of interest:

  • Additional typed segment extensions (120+ segments in the HL7v2 spec)
  • Version-specific schema validation
  • Additional test fixtures from real hospital systems

Please file issues on GitHub.

License #

BSD-3-Clause. See LICENSE.

0
likes
160
points
118
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Parse, generate, and access HL7v2 messages in Dart. Lazy parser, typed segment extensions, Terser path access, ACK/NAK generation. Zero dependencies, all platforms.

Homepage
Repository (GitHub)
View/report issues

Topics

#hl7 #hl7v2 #healthcare #parser #interoperability

License

BSD-3-Clause (license)

More

Packages that depend on hl7v2_parser