UNPKG

@loaders.gl/geoarrow

Version:

GeoArrow columnar geometry encoding and decoding

132 lines (131 loc) 4.85 kB
// loaders.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors /* eslint-disable camelcase */ import { getMetadataValue, setMetadataValue } from "./metadata-utils.js"; // GEO METADATA /** * Reads the GeoMetadata object from the metadata * @note geoarrow / parquet schema is stringified into a single key-value pair in the parquet metadata */ export function getGeoMetadata(metadata) { const stringifiedGeoMetadata = getMetadataValue(metadata, 'geo'); const geoMetadata = stringifiedGeoMetadata && parseJSONStringMetadata(stringifiedGeoMetadata); if (!geoMetadata) { return null; } for (const column of Object.values(geoMetadata.columns || {})) { if (column.encoding) { column.encoding = column.encoding.toLowerCase(); } } return geoMetadata; } /** * Stores a geoarrow / geoparquet geo metadata object in the schema * @note geoarrow / geoparquet geo metadata is a single stringified JSON field */ export function setGeoMetadata(metadata, geoMetadata) { const stringifiedGeoMetadata = JSON.stringify(geoMetadata); setMetadataValue(metadata, 'geo', stringifiedGeoMetadata); } /** * Unpacks geo metadata into separate metadata fields (parses the long JSON string) * @note geoarrow / parquet schema is stringified into a single key-value pair in the parquet metadata */ export function unpackGeoMetadata(metadata) { const geoMetadata = getGeoMetadata(metadata); if (!geoMetadata) { return; } // Store Parquet Schema Level Metadata const { version, primary_column, columns } = geoMetadata; if (version) { setMetadataValue(metadata, 'geo.version', version); } if (primary_column) { setMetadataValue(metadata, 'geo.primary_column', primary_column); } // store column names as comma separated list setMetadataValue(metadata, 'geo.columns', Object.keys(columns || {}).join('')); // for (const [columnName, columnMetadata] of Object.entries(columns || {})) { // const field = schema.fields.find((field) => field.name === columnName); // if (field) { // if (field.name === primary_column) { // setFieldMetadata(field, 'geo.primary_field', 'true'); // } // unpackGeoFieldMetadata(field, columnMetadata); // } // } } export function unpackJSONStringMetadata(metadata, metadataKey) { const stringifiedGeoMetadata = getMetadataValue(metadata, 'geo'); const json = stringifiedGeoMetadata && parseJSONStringMetadata(stringifiedGeoMetadata); for (const [key, value] of Object.entries(json || {})) { setMetadataValue(metadata, `${metadataKey}.${key}`, typeof value === 'string' ? value : JSON.stringify(value)); } } // eslint-disable-next-line complexity // function unpackGeoFieldMetadata(fieldMetadata: Metadata, columnMetadata): void { // for (const [key, value] of Object.entries(columnMetadata || {})) { // switch (key) { // case 'geometry_types': // setFieldMetadata(field, `geo.${key}`, (value as string[]).join(',')); // break; // case 'bbox': // setFieldMetadata(field, `geo.crs.${key}`, JSON.stringify(value)); // break; // case 'crs': // // @ts-ignore // for (const [crsKey, crsValue] of Object.entries(value || {})) { // switch (crsKey) { // case 'id': // // prettier-ignore // const crsId = // typeof crsValue === 'object' // ? // @ts-ignore // `${crsValue?.authority}:${crsValue?.code}` // : JSON.stringify(crsValue); // setFieldMetadata(field, `geo.crs.${crsKey}`, crsId); // break; // default: // setFieldMetadata( // field, // `geo.crs.${crsKey}`, // typeof crsValue === 'string' ? crsValue : JSON.stringify(crsValue) // ); // break; // } // } // break; // case 'edges': // default: // setFieldMetadata( // field, // `geo.${key}`, // typeof value === 'string' ? value : JSON.stringify(value) // ); // } // } // } // function setFieldMetadata(field: Field, key: string, value: string): void { // field.metadata = field.metadata || {}; // field.metadata[key] = value; // } // HELPERS /** Parse a key with stringified arrow metadata */ export function parseJSONStringMetadata(stringifiedMetadata) { if (!stringifiedMetadata) { return null; } try { const metadata = JSON.parse(stringifiedMetadata); if (!metadata || typeof metadata !== 'object') { return null; } return metadata; } catch { return null; } }