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)
elementType — required — 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
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 |
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
src/ogc-api/csapi/formats/swecommon/data-array.tssrc/ogc-api/csapi/formats/swecommon/data-array.spec.tsBlueprint Reference
Follow the EDR pattern in
src/ogc-api/edr/model.ts(126 lines) for file structure andsrc/ogc-api/edr/model.spec.ts(42 lines) for test patterns.Scope — What to Implement
DataArray Parser
parseDataArray(json: unknown): DataArrayParse 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 identifierlabel?: string— human-readable label (from AbstractSweIdentifiable)description?: string— human-readable description (from AbstractSweIdentifiable)definition?: string— URI semantic link defining what this array representsupdatable?: boolean— whether value can be updated externally (default: false)optional?: boolean— whether data can be omitted in datastream (default: false)elementType— required — defines the structure of the repeated element. Per OGC spec, this is a named property: it has a requiredname(pattern^[A-Za-z][A-Za-z0-9_\-]*$) plus either an inlineAnyComponentor a link reference (href,role,arcrole,title). Uses the sameSoftNamedPropertywrapper 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 blockvalues?: EncodedValues— encoded block of array values (array or link reference)Required fields per spec:
typeandelementTypeonly.Encoding Parsers
parseEncoding(json: unknown): DataEncodingParse 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'— requiredrecordsAsArrays?: 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'— requiredtokenSeparator: 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 separatorsBinary 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'— requiredbyteOrder: 'bigEndian' | 'littleEndian'— requiredbyteEncoding: 'base64' | 'raw'— requiredbyteLength?: number— total stream length if knownmembers: BinaryMember[]— required (minItems: 1), each is oneOf:{ type: 'Component', ref: string, dataType: string (URI), encryption?: string, significantBits?: integer, bitLength?: integer, byteLength?: integer }— required:type,dataType,ref{ type: 'Block', ref: string, compression?: string, encryption?: string, 'paddingBytes-after'?: integer, 'paddingBytes-before'?: integer, byteLength?: integer }— required:type,refNote: 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:
recordsAsArrays)blockSeparatorinto records, then bytokenSeparatorinto fields, applyingdecimalSeparatorfor numeric conversionbyteOrder,membersconfiguration, and data typeshref— preserve the link for downstream resolutionError Handling
typeortype !== 'DataArray'→ errorelementType→ error (required per spec)elementTypemissingname→ error (required per SoftNamedProperty)type→ error with the unrecognized type valuetokenSeparatororblockSeparator→ errorbyteOrder,byteEncoding, ormembers→ errorJSDoc Requirements
parseDataArraywith@param,@returns, and usage example showing JSON-encoded arrayparseEncodingwith examples of each encoding typedecodeValueswith encoding-specific examples@seelink to OGC SWE Common 3.0 (24-014) DataArray and encoding sectionssrc/ogc-api/edr/model.tsTesting Requirements
src/ogc-api/csapi/formats/swecommon/data-array.spec.ts(~150-200 lines)recordsAsArrays: truecollapseWhiteSpacesbehaviorsrc/ogc-api/edr/model.spec.tsScope — What NOT to Touch
types.ts— that belongs to Issue Phase 3.4: SWE Common Types #17 (SWE Common Types)components.ts— that belongs to Issue Phase 3, Task 11: SWE Common Simple Components Parser #24 (SWE Common Simple Components Parser)data-record.ts— that belongs to Issue Phase 3, Task 12: SWE Common DataRecord Parser #25 (SWE Common DataRecord Parser)parser.ts— that belongs to Issue Phase 3, Task 14: SWE Common Main Parser #27 (SWE Common Main Parser)index.ts— that belongs to Issue Phase 3, Task 15: SWE Common Index #28 (SWE Common Index)Acceptance Criteria
data-array.tsexists withparseDataArray(),parseEncoding(), anddecodeValues()functionselementTypewith name extraction (SoftNamedProperty wrapper) and component delegationelementCount(Count component or link reference)type,elementType)@seespec referencesdata-array.spec.tsexists with tests for all three encodings, element count, element type, and error handlingnpm test)Dependencies
Blocked by: Issue #17 — SWE Common Types (must have
DataArray,DataEncoding,ElementCountinterfaces), 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
parseDataArrayand encoding utilities)Operational Constraints
Key constraints for this task:
References
Read these documents before starting implementation. They are ordered by priority.
Primary References (must read)
docs/planning/csapi-implementation-guide.mddocs/planning/csapi-implementation-guide.mddata-array.ts(~200-250 lines)docs/planning/csapi-implementation-guide.mdDataArray,DataEncoding,TextEncoding,BinaryEncoding,JSONEncodinginterfacessrc/ogc-api/edr/model.tssrc/ogc-api/edr/model.spec.tsUpstream Type/Import References (files this task imports from)
src/ogc-api/csapi/formats/swecommon/types.tsDataArray,DataEncoding,JSONEncoding,TextEncoding,BinaryEncoding,BinaryMember,ElementCount,EncodedValues,SWEDataComponentsrc/ogc-api/csapi/formats/swecommon/components.tsparseSimpleComponentfor element type parsing delegationsrc/ogc-api/csapi/formats/swecommon/data-record.tsparseDataRecordfor complex element typesResearch References (context, not required reading)
docs/research/requirements/csapi-datatype-schema-requirements.mddocs/research/testing/findings/04-implementation-guide-testing-requirements.mdSpecification References (for
@seelinks and field accuracy)docs/research/standards/ogcapi-connectedsystems-2.bundled.oas31.yamlDataArray(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
.jsextension for relative importsimport { X } from './file.js'import typefor interfaces/typesimport type { Y } from './model.js'export interface Z { ... }as constarrays for enum-like valuesexport const XTypes = [...] as constglobalThis.fetch = jest.fn()