Skip to content

Phase 3, Task 13: SWE Common DataArray Parser #26

@Sam-Bolling

Description

@Sam-Bolling

Task

Create the SWE Common DataArray parser (data-array.ts) that parses DataArray structures with a named element type, optional element count, encoding specification, and encoded values block. Support all three primary encodings: JSON, Text, and Binary.

ROADMAP Reference: Phase 3, Task 13 — SWE Common DataArray Parser (~2-3 hours, Medium-High complexity)


Files to Create or Modify

File Action Est. Lines Purpose
src/ogc-api/csapi/formats/swecommon/data-array.ts Create ~200-250 DataArray parser with encoding support
src/ogc-api/csapi/formats/swecommon/data-array.spec.ts Create ~150-200 DataArray parser tests — JSON/Text/Binary encodings, element count

Blueprint Reference

Follow the EDR pattern in src/ogc-api/edr/model.ts (126 lines) for file structure and src/ogc-api/edr/model.spec.ts (42 lines) for test patterns.

Scope — What to Implement

DataArray Parser

parseDataArray(json: unknown): DataArray

Parse a SWE Common 3.0 DataArray structure. A DataArray is an implementation of the ISO-11404 Array datatype that defines an array of identical data components with an element count. Values are given as a block and can be encoded in different ways (JSON, Text, Binary).

Properties to parse:

  • type: 'DataArray' — discriminator (required, must be 'DataArray')
  • id?: string — optional referenceable identifier
  • label?: string — human-readable label (from AbstractSweIdentifiable)
  • description?: string — human-readable description (from AbstractSweIdentifiable)
  • definition?: string — URI semantic link defining what this array represents
  • updatable?: boolean — whether value can be updated externally (default: false)
  • optional?: boolean — whether data can be omitted in datastream (default: false)
  • elementTyperequired — defines the structure of the repeated element. Per OGC spec, this is a named property: it has a required name (pattern ^[A-Za-z][A-Za-z0-9_\-]*$) plus either an inline AnyComponent or a link reference (href, role, arcrole, title). Uses the same SoftNamedProperty wrapper as DataRecord fields.
  • elementCount?: ElementCount — specifies the size of the array. OneOf: a Count component (with optional integer value) or a link reference.
  • encoding?: DataEncoding — specifies the encoding method for the values block
  • values?: EncodedValues — encoded block of array values (array or link reference)

Required fields per spec: type and elementType only.

Encoding Parsers

parseEncoding(json: unknown): DataEncoding

Parse the encoding specification. The OGC spec defines four encoding types; we implement three primary ones:

JSON Encoding (JSONEncoding):

{
  "type": "JSONEncoding",
  "recordsAsArrays": false,
  "vectorsAsArrays": false
}
  • type: 'JSONEncoding' — required
  • recordsAsArrays?: boolean — if true, DataRecord values encoded as JSON arrays instead of objects (default: false)
  • vectorsAsArrays?: boolean — if true, Vector values encoded as JSON arrays instead of objects (default: false)

Text Encoding (TextEncoding):

{
  "type": "TextEncoding",
  "tokenSeparator": ",",
  "blockSeparator": "\n",
  "decimalSeparator": ".",
  "collapseWhiteSpaces": true
}
  • type: 'TextEncoding' — required
  • tokenSeparator: string — required, character between successive values (e.g., ,)
  • blockSeparator: string — required, character between blocks (e.g., \n)
  • decimalSeparator?: string — decimal character (default: .)
  • collapseWhiteSpaces?: boolean — whether to collapse whitespace with separators

Binary Encoding (BinaryEncoding):

{
  "type": "BinaryEncoding",
  "byteOrder": "bigEndian",
  "byteEncoding": "base64",
  "byteLength": 1024,
  "members": [
    { "type": "Component", "ref": "temperature", "dataType": "http://www.opengis.net/def/dataType/OGC/0/float64" },
    { "type": "Block", "ref": "imageData", "compression": "http://www.opengis.net/def/encoding/OGC/0/gzip" }
  ]
}
  • type: 'BinaryEncoding' — required
  • byteOrder: 'bigEndian' | 'littleEndian' — required
  • byteEncoding: 'base64' | 'raw' — required
  • byteLength?: number — total stream length if known
  • members: BinaryMember[] — required (minItems: 1), each is oneOf:
    • Component: { type: 'Component', ref: string, dataType: string (URI), encryption?: string, significantBits?: integer, bitLength?: integer, byteLength?: integer } — required: type, dataType, ref
    • Block: { type: 'Block', ref: string, compression?: string, encryption?: string, 'paddingBytes-after'?: integer, 'paddingBytes-before'?: integer, byteLength?: integer } — required: type, ref

Note: The OGC spec also defines XMLEncoding ({ type: 'XMLEncoding', namespace?: uri }). This should be recognized (to avoid parse errors) but is low priority for the JSON API context. At minimum, parse its type discriminator and preserve properties; full XML value decoding is out of scope.

Values Decoding

decodeValues(values: unknown, encoding: DataEncoding, elementType: SWEDataComponent): unknown[]

Decode the values block according to the encoding:

  • JSON encoding: Values are already structured JSON (array of objects or arrays depending on recordsAsArrays)
  • Text encoding: Values are a string — split by blockSeparator into records, then by tokenSeparator into fields, applying decimalSeparator for numeric conversion
  • Binary encoding: Values are a base64-encoded or raw binary block — decode bytes according to byteOrder, members configuration, and data types
  • Link reference: Values provided via href — preserve the link for downstream resolution

Error Handling

  • Missing type or type !== 'DataArray' → error
  • Missing elementType → error (required per spec)
  • elementType missing name → error (required per SoftNamedProperty)
  • Invalid encoding type → error with the unrecognized type value
  • Text encoding missing required tokenSeparator or blockSeparator → error
  • Binary encoding missing required byteOrder, byteEncoding, or members → error
  • Values/encoding mismatch (e.g., text values with binary encoding) → error
  • Meaningful error messages indicating the DataArray context

JSDoc Requirements

  • Document parseDataArray with @param, @returns, and usage example showing JSON-encoded array
  • Document parseEncoding with examples of each encoding type
  • Document decodeValues with encoding-specific examples
  • Add @see link to OGC SWE Common 3.0 (24-014) DataArray and encoding sections
  • Follow the JSDoc style in src/ogc-api/edr/model.ts

Testing Requirements

  • Create src/ogc-api/csapi/formats/swecommon/data-array.spec.ts (~150-200 lines)
  • JSON encoding tests:
    • Array with JSON-encoded values (objects)
    • Array with recordsAsArrays: true
    • Default encoding options applied
  • Text encoding tests:
    • Array with comma-separated values
    • Custom separators (token, block, decimal)
    • collapseWhiteSpaces behavior
  • Binary encoding tests:
    • Base64-encoded binary block
    • Component and Block member types
    • Big-endian and little-endian byte order
  • Element count tests:
    • Count with integer value
    • Count as link reference
    • No element count (optional)
  • Element type tests:
    • Simple element type (Quantity)
    • Complex element type (DataRecord)
    • Element type with name wrapper validated
    • Element type as link reference
  • Error handling tests:
    • Missing elementType → error
    • Invalid encoding type → error
    • Missing required encoding properties → error
    • Null/undefined input → error
  • Follow test patterns from src/ogc-api/edr/model.spec.ts

Scope — What NOT to Touch

Acceptance Criteria

  • data-array.ts exists with parseDataArray(), parseEncoding(), and decodeValues() functions
  • Parses elementType with name extraction (SoftNamedProperty wrapper) and component delegation
  • Parses elementCount (Count component or link reference)
  • Parses all three primary encoding types: JSON, Text, Binary
  • Recognizes XMLEncoding type discriminator (no full XML decoding required)
  • Decodes JSON-encoded values (objects and arrays modes)
  • Decodes Text-encoded values (with configurable separators)
  • Handles Binary encoding specification (base64/raw, Component/Block members)
  • Validates required properties (type, elementType)
  • Validates encoding-specific required properties
  • All new code has complete JSDoc documentation with @see spec references
  • data-array.spec.ts exists with tests for all three encodings, element count, element type, and error handling
  • Existing tests still pass (npm test)
  • No lint errors

Dependencies

Blocked by: Issue #17 — SWE Common Types (must have DataArray, DataEncoding, ElementCount interfaces), Issue #24 — SWE Common Simple Components Parser (for element type parsing), Issue #25 — SWE Common DataRecord Parser (for complex element types)
Blocks: Issue #27 — SWE Common Main Parser (imports parseDataArray and encoding utilities)


Operational Constraints

⚠️ MANDATORY: Before starting work on this issue, review docs/governance/AI_OPERATIONAL_CONSTRAINTS.md.

Key constraints for this task:

  • Precedence: OGC specifications → AI Collaboration Agreement → This issue description → Existing code → Conversational context
  • No scope expansion: Do not infer unstated requirements or add unrequested features
  • No refactoring: Do not rename, restructure, or "improve" code outside this issue's scope
  • Minimal diffs: Prefer the smallest change that satisfies the acceptance criteria
  • Ask when unclear: If intent is ambiguous, stop and ask for clarification

References

Read these documents before starting implementation. They are ordered by priority.

Primary References (must read)

# Document Section/Lines What It Provides
1 docs/planning/csapi-implementation-guide.md Lines 3043-3130 (SWE Common Handler) Full specification of SWE Common data components and encodings
2 docs/planning/csapi-implementation-guide.md Lines 2098-2120 (File Structure) File organization showing data-array.ts (~200-250 lines)
3 docs/planning/csapi-implementation-guide.md Lines 2838-2910 (SWE Common Types) DataArray, DataEncoding, TextEncoding, BinaryEncoding, JSONEncoding interfaces
4 src/ogc-api/edr/model.ts Full file (126 lines) Blueprint — file structure, JSDoc style, export conventions
5 src/ogc-api/edr/model.spec.ts Full file (42 lines) Blueprint — test structure and patterns

Upstream Type/Import References (files this task imports from)

# Document What to Import
1 src/ogc-api/csapi/formats/swecommon/types.ts DataArray, DataEncoding, JSONEncoding, TextEncoding, BinaryEncoding, BinaryMember, ElementCount, EncodedValues, SWEDataComponent
2 src/ogc-api/csapi/formats/swecommon/components.ts parseSimpleComponent for element type parsing delegation
3 src/ogc-api/csapi/formats/swecommon/data-record.ts parseDataRecord for complex element types

Research References (context, not required reading)

# Document What It Provides
1 docs/research/requirements/csapi-datatype-schema-requirements.md Complete analysis of SWE Common data types including DataArray
2 docs/research/testing/findings/04-implementation-guide-testing-requirements.md Testing requirements and fixture definitions

Specification References (for @see links and field accuracy)

# Document Use
1 OGC SWE Common 3.0 (24-014) Normative specification for DataArray structure and encoding methods
2 OGC API - Connected Systems Part 2 (23-002) DataArray usage in DataStream result schemas and Observation results
3 docs/research/standards/ogcapi-connectedsystems-2.bundled.oas31.yaml OpenAPI schema — DataArray (L7638), element type with SoftNamedProperty (L1127-1136), encoding types (L1138-1300: Binary L1141, Text L1246, XML L1273, JSON L1286), values block (L1304-1310), required fields (L1314-1316: type + elementType)

Convention Quick Reference

Rule Example
Use .js extension for relative imports import { X } from './file.js'
Use import type for interfaces/types import type { Y } from './model.js'
Three-tier hierarchy: import from lower tiers only shared → ogc-api → csapi
Named exports for types and utilities export interface Z { ... }
as const arrays for enum-like values export const XTypes = [...] as const
HTTP mocking: globalThis.fetch = jest.fn() Never use nock, msw, or other libraries
Meaningful tests only Verify behavior, not that code runs without throwing

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions