JSON Mapping

pg_ripple's JSON mapping feature provides a bidirectional bridge between JSON payloads and the RDF knowledge graph. Register a named JSON-LD context once with register_json_mapping(), then use it for both ingest and export.

Registration

SELECT pg_ripple.register_json_mapping(
    'contacts',
    '{"contact_id": "http://schema.org/identifier",
      "full_name":  "http://schema.org/name",
      "email_addr": "http://schema.org/email"}'::jsonb
);

Parameters:

ParameterDescription
nameUnique mapping name
contextJSON-LD @context object mapping JSON keys to RDF predicate IRIs
shape_iriOptional SHACL shape for consistency validation
default_graph_iriDefault named graph for ingested triples
timestamp_pathJSONPath to root timestamp field (diff mode)
timestamp_predicateRDF predicate for per-triple change timestamps
iri_templateIRI template with {id} placeholder
iri_match_patternPrefix or regex for late-binding IRI rewrite

Ingest (JSON → RDF)

SELECT pg_ripple.ingest_json(
    '{"contact_id": "c001", "full_name": "Alice Smith"}'::jsonb,
    'https://example.com/contacts/c001',
    'contacts'
);

Modes: 'append' (default), 'upsert', 'diff'.

Export (RDF → JSON)

SELECT pg_ripple.export_json_node(subject_id, 'contacts');

Relational Writeback (v0.128.0)

v0.128.0 adds the ability to write RDF graph changes back to the originating relational table — completing the full round-trip.

Configuration

Add writeback configuration to the mapping:

UPDATE _pg_ripple.json_mappings
SET writeback_table        = 'contacts',
    writeback_schema       = 'public',
    writeback_key_columns  = ARRAY['contact_id'],
    writeback_conflict_policy = 'replace'
WHERE name = 'contacts';

Conflict Policies

PolicyBehaviour
'replace' (default)ON CONFLICT (key_cols) DO UPDATE SET …
'skip'ON CONFLICT DO NOTHING — returns 0 rows
'error'Raises PT0551 on conflict

Direct Writeback

-- Write a single subject back to the relational table.
SELECT pg_ripple.writeback_json_row('contacts', 'https://example.com/contacts/c001');

-- Delete a subject from the relational table.
SELECT pg_ripple.writeback_json_row_delete('contacts', 'https://example.com/contacts/c001');

Trigger-Based Automation

Enable VP delta triggers for automatic async writeback:

SELECT pg_ripple.enable_json_writeback('contacts');

The background merge worker drains the queue in batches (controlled by pg_ripple.json_writeback_batch_size, default 100).

Monitor queue status:

SELECT * FROM pg_ripple.json_writeback_status();
--  mapping_name | pending | errors | last_error | last_processed_at

HTTP Writeback

The HTTP companion exposes the same writeback path for applications that do not call SQL directly:

curl -X POST http://localhost:7878/json-mapping/contacts/writeback \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"subject_iri":"https://example.com/contacts/c001"}'

Successful synchronous writeback returns:

{"rows_affected": 1}

Queue status for one mapping is available over HTTP as well:

curl http://localhost:7878/json-mapping/contacts/writeback/status \
    -H "Authorization: Bearer $TOKEN"

The status response mirrors json_writeback_status() for the selected mapping:

{
    "mapping_name": "contacts",
    "pending": 0,
    "errors": 0,
    "last_error": null,
    "last_processed_at": null
}

Disable triggers:

SELECT pg_ripple.disable_json_writeback('contacts');

Both enable_json_writeback() and disable_json_writeback() are idempotent.

Error Codes

CodeMessage
PT0550json mapping writeback target not configuredwriteback_table is NULL or writeback_key_columns is empty
PT0551json mapping writeback conflict — conflict detected with policy 'error'

See Also