# Serializing and sharing

> Write a Well back to .well text with serializeWell, keep unknown members, check whether a well holds data, and redact sections before sharing a file.

## `serializeWell`

```ts
import { serializeWell } from '@welldot/core';

const text = serializeWell(well); // a JSON string, ready to save as .well
```

`serializeWell(well: Well): string` writes the current format:

- `"version": "2.4"` (the value of `WELL_FORMAT_VERSION`), whatever version the file was read from;
- `location` as an object, never the v1 flat `lat` / `lng` / `elevation`;
- no `null` and no `undefined` optional fields, as the spec requires ([absent values](/format/spec/v2/format-reference#absent-values-since-v24)), except inside `x-` members and `@context`, which are written as they are;
- every root member the spec does not define (`x-` fields and blocks, foreign members) unchanged, after the spec blocks ([extensibility](/format/spec/v2/format-reference#extensibility)).

The output is compact JSON. To store it indented, re-indent it:

```ts
const pretty = JSON.stringify(JSON.parse(serializeWell(well)), null, 2);
```

## Round trips keep what you did not touch

`parseWell` keeps unknown members at every level, and `serializeWell` writes them back. A tool that reads a file, edits a field and saves it therefore preserves extensions it has never heard of:

```ts
import { parseWell, serializeWell } from '@welldot/core';

const well = parseWell(
  '{"version":2,"x-acme":{"asset":"A-7"},"bore_hole":[{"from":0,"to":60,"diameter":254,"x-acme-bit":"PDC"}],' +
    '"well_case":[],"reduction":[],"well_screen":[],"surface_case":[],"hole_fill":[],' +
    '"lithology":[],"fractures":[],"caves":[]}',
);
well.name = 'PT-07';
serializeWell(well);
// {"version":"2.4","name":"PT-07","bore_hole":[{"from":0,"to":60,"diameter":254,"x-acme-bit":"PDC"}],
//  …,"x-acme":{"asset":"A-7"}}
```

::warning
Spreading a well into a new object of only the fields you know (`{ name, bore_hole, … }`) drops unknown members. Edit the parsed object in place, or copy it whole with `structuredClone`.
::

## Empty or not

Two helpers answer different questions:

| Helper              | `true` when                                                                                                                                          |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `isWellEmpty(well)` | There is nothing to draw: every construction and geology array is empty.                                                                             |
| `hasWellData(well)` | The well holds any data at all: a profile, identification, location, events, samples, permits or `x-` members. Blank strings and zeros do not count. |

A registry record with a location and a permit but no construction has data (`hasWellData` is `true`) and nothing to draw (`isWellEmpty` is `true`). Both accept `null` and `undefined`.

`calculatedWellDepth(well)` returns the deepest `to` across the construction arrays, ignoring geology, or `0`. Use it when `well_depth` is absent and you need the drilled depth ([Depths and intervals](/format/concepts/depths-and-intervals)).

## Redacting before sharing

To publish a well without some of its data, such as a private owner's location or permits, use `redactWell`. It returns a copy with the hidden parts removed (arrays emptied, optional fields deleted), so the result is still a valid `.well` file.

```ts
import { redactWell, serializeWell } from '@welldot/core';

// Hide a whole section
const publicWell = redactWell(well, { operation: false });

// Or individual fields
const anonymous = redactWell(well, {
  location: false,
  permits: false,
  meters: false,
});

serializeWell(publicWell);
```

Keys are the seven sections or the fields within them; `false` hides, a missing key stays visible, and hiding a section hides all its fields:

| Section         | Fields                                                                                                          |
| --------------- | --------------------------------------------------------------------------------------------------------------- |
| `general`       | `identification`, `location`, `obs`, `attachments`                                                              |
| `constructive`  | `bore_hole`, `surface_case`, `well_case`, `reduction`, `well_screen`, `hole_fill`, `centralizers`, `cement_pad` |
| `geology`       | `lithology`, `fractures`, `caves`                                                                               |
| `hydrodynamic`  | `hydrodynamic_events`, `aquifer_analysis`                                                                       |
| `history`       | (the whole section)                                                                                             |
| `operation`     | `pump_installations`, `meters`, `operating_regime`, `production`, `permits`                                     |
| `water_quality` | (the whole section)                                                                                             |

The same structure is exported as `SECTION_KEYS`, `VISIBILITY_TREE` and `VISIBILITY_LEAF_KEYS`, for building a visibility form.

References from visible records to hidden ones are left as they are; they become dangling references, which readers report as warnings ([dangling references](/format/spec/v2/format-reference#dangling-references)). Unknown root members (`x-` blocks) are kept only when nothing is hidden, since `redactWell` cannot know whether they are private.

## Related

- [`serializeWell`](/core/api/functions/serializeWell), [`redactWell`](/core/api/functions/redactWell), [`hasWellData`](/core/api/functions/hasWellData) in the API reference
- [Building on .well](/format/guides/building-on-well)
