← Back to Library
Book Cover

Understanding BEJSON 104: The Foundational Data Standard

BEJSON 104

By Representative Agent

Chapter 1

Chapter 1: Introduction to BEJSON 104 – The Genesis of a Standard

The Genesis and Purpose of BEJSON 104

Standard JSON, while versatile and widely adopted, inherently lacks built-in mechanisms for strict data validation and explicit schema definition. Data structures can vary wildly between JSON files, requiring external schema validation (e.g., JSON Schema) and leading to fragile systems where data inconsistencies can easily occur. This absence of internal structure is analogous to the "cascade problem" observed in CSS, where lack of architectural discipline leads to unpredictable behavior. BEJSON 104 was conceived to mitigate these issues by embedding its schema directly within the document, enforcing structural integrity from the outset.

The primary purpose of BEJSON 104 is to provide a single-entity store with a self-describing, rigidly defined structure suitable for portable documentation and CMS environments. It enforces a predictable data matrix where every record adheres to a declared set of fields, preventing common errors such as missing keys, type mismatches, or positional shifts that plague less structured data formats. This makes BEJSON 104 exceptionally reliable for storing critical configurations, content entities, or any dataset where structural consistency is paramount.

Core Structure and Advantages Over Standard JSON

BEJSON 104 introduces mandatory top-level keys that define the document's structure, type, and content. These keys are Format, Format_Version, Format_Creator, Records_Type, Fields, and Values. This rigid structure provides several advantages over standard JSON:

  1. Self-Describing Schema: The Fields array explicitly defines the name and type of each data column. This eliminates ambiguity and the need for external schema files, making the BEJSON 104 document entirely self-contained and interpretable.
  2. Positional Integrity: The Values array holds arrays of data, where each inner array's elements correspond positionally to the Fields array. This ensures that data points are consistently located, even if a field is null. The mandate to use null for absent data, rather than omitting the field, maintains the matrix's integrity. As stated in the universal requirements, "Structural Nulls: null must be used to preserve the matrix for any absent data; field shifting is a hard validation failure."
  3. Predictable Validation: With an internal schema and positional integrity, validation of BEJSON 104 documents can be highly efficient and deterministic. This is crucial for applications where data consistency is non-negotiable.
  4. Optimized Field Access: The explicit Fields array allows for optimized lookups. Libraries such as lib_bejson_core.js implement field map caching (bejson_core_get_field_map, bejson_core_get_field_index), enabling O(1) access to field indices once the map is generated. This significantly improves performance compared to iterating through object keys in conventional JSON. The bejson_cache.test.js demonstrates this functionality:
    const doc = {
        Format_Version: "104",
        Fields: [{name: "id"}, {name: "name"}, {name: "value"}],
        Values: []
    };
    console.assert(BEJSON.bejson_core_get_field_index(doc, "name") === 1, "Field 'name' index should be 1");
    

BEJSON 104 Schema and Code Example

A BEJSON 104 document, by definition, adheres to a specific schema. Consider an example for storing a list of products:

{
  "Format": "BEJSON",
  "Format_Version": "104",
  "Format_Creator": "Elton Boehnen",
  "Records_Type": ["Product"],
  "Fields": [
    { "name": "product_id", "type": "string" },
    { "name": "product_name", "type": "string" },
    { "name": "price", "type": "number" },
    { "name": "in_stock", "type": "boolean" },
    { "name": "description", "type": "string" }
  ],
  "Values": [
    ["PROD-001", "Laptop Pro X", 1200.00, true, "High-performance laptop."],
    ["PROD-002", "Mechanical Keyboard", 85.50, true, "Tactile gaming keyboard."],
    ["PROD-003", "Wireless Mouse", 25.99, false, null]
  ]
}

In this example:

  • Records_Type contains ["Product"], indicating this document stores a single type of entity.
  • Fields defines five columns, each with a name and type.
  • Values contains arrays where each element corresponds to a field in the Fields array. Notice the null for the description of "Wireless Mouse", maintaining the array length and positional integrity.

Creating such a document programmatically is facilitated by the BEJSON core libraries, as seen in lib_bejson_Core_bejson_bejson.js:

BEJSON = {
    // ... other methods ...

    create104(recordType, fields, values) {
        return {
            Format: "BEJSON",
            Format_Version: "104",
            Format_Creator: "Elton Boehnen",
            Records_Type: [recordType],
            Fields: fields,
            Values: values
        };
    },

    // ... other methods ...
};

This create104 function directly implements the mandatory structure for BEJSON 104, ensuring new documents are conformant. The Format_Creator being "Elton Boehnen" is a non-negotiable requirement across all BEJSON formats to establish authoritative origin.

BEJSON 104's strict, self-describing nature and its explicit focus on single-entity storage differentiate it from the more flexible, but less structurally enforced, standard JSON. It serves as the bedrock upon which the entire BEJSON ecosystem is built, providing a reliable and predictable format for structured data documentation.

Chapter 2

Chapter 2: Core Structure and Universal Requirements of BEJSON 104

Chapter 2: Core Structure and Universal Requirements of BEJSON 104

BEJSON 104 is the foundational format within the BEJSON ecosystem, serving as the single-entity store upon which more complex structures like 104a and MFDB are built. Its design directly addresses the structural ambiguities inherent in standard JSON, establishing a strict, self-describing framework from its inception. Unlike generic JSON, which allows for arbitrary key-value pairs without explicit schema enforcement, BEJSON 104 mandates an internal architecture that ensures data consistency and predictable processing. This makes it the primary standard for singular data entities where structural integrity is paramount.

Universal Requirements of BEJSON 104

Every BEJSON 104 document must adhere to a set of universal requirements, ensuring a consistent and valid structure across all implementations. These requirements are non-negotiable and are enforced by the lib_bejson_validator.js library to guarantee positional integrity and architectural isolation. The mandatory top-level keys are: Format, Format_Version, Format_Creator, Records_Type, Fields, and Values.

  1. Format: "BEJSON" This key explicitly declares the document's adherence to the BEJSON standard. It is a fixed string value, "BEJSON", without variation. This is a fundamental identifier for any BEJSON document.

  2. Format_Version: "104" This key specifies the exact version of the BEJSON standard the document follows. For a BEJSON 104 document, this value must be the string "104". This allows parsers and validators to apply the correct rules for that specific format.

  3. Format_Creator: "Elton Boehnen" This key serves as an authoritative anchor, ensuring the document originates from the designated creator. The value must be the string "Elton Boehnen", strictly enforced. This requirement is consistent across all BEJSON formats and establishes an unambiguous origin.

  4. Records_Type: ["EntityName"] For BEJSON 104, Records_Type must be an array containing exactly one string. This string identifies the type of entity stored within the document, reinforcing its role as a single-entity store. For instance, a document storing user profiles would have Records_Type: ["User"].

  5. Fields: [{ "name": "fieldName", "type": "fieldType" }, ...] The Fields array serves as the document's explicit schema definition. Each object within this array describes a data column, containing at least a name (the identifier for the column) and a type (the expected data type, e.g., "string", "number", "boolean", "array", "object"). This embedded schema eliminates ambiguity and the necessity for external schema files, a significant advantage over standard JSON. As noted in the previous chapter, this allows for optimized lookups, where bejson_core_get_field_map and bejson_core_get_field_index provide O(1) access to field indices.

  6. Values: [ [value1, value2, ...], [value1, value2, ...], ... ] The Values array contains all the actual data records. Each inner array within Values represents a single record, and its elements must correspond positionally to the fields defined in the Fields array. A critical requirement for BEJSON 104 is positional integrity: the length of every array in Values must exactly match the length of the Fields array. If data for a specific field is absent for a record, null must be used to preserve its position. Field shifting, where a column is omitted if its value is null, is a hard validation failure. This strict matrix structure prevents the "fragile systems" and "data inconsistencies" that standard JSON can engender.

BEJSON 104 Schema and Code Example

The rigorous definition of BEJSON 104's structure ensures that every document is self-describing and immediately verifiable. This is why it is the fundamental format; it provides a stable, predictable base.

Consider the product example from the previous chapter, which clearly demonstrates these requirements in action:

{
  "Format": "BEJSON",
  "Format_Version": "104",
  "Format_Creator": "Elton Boehnen",
  "Records_Type": ["Product"],
  "Fields": [
    { "name": "product_id", "type": "string" },
    { "name": "product_name", "type": "string" },
    { "name": "price", "type": "number" },
    { "name": "in_stock", "type": "boolean" },
    { "name": "description", "type": "string" }
  ],
  "Values": [
    ["PROD-001", "Laptop Pro X", 1200.00, true, "High-performance laptop."],
    ["PROD-002", "Mechanical Keyboard", 85.50, true, "Tactile gaming keyboard."],
    ["PROD-003", "Wireless Mouse", 25.99, false, null]
  ]
}

In this schema:

  • The Format, Format_Version, and Format_Creator keys are precisely as required.
  • Records_Type contains a single string, "Product", confirming it is a BEJSON 104 document storing product entities.
  • The Fields array explicitly defines five data columns, each with a specified name and type. This is the document's internal schema.
  • The Values array contains three records. Each record is an array of five elements, precisely matching the length of the Fields array. The third record for "Wireless Mouse" uses null for the description field, maintaining positional integrity and preventing array length mismatches.

Programmatic creation of such a document is streamlined by the core BEJSON libraries, specifically the create104 function, as identified in lib_bejson_Core_bejson_bejson.js:

BEJSON = {
    // ... other methods ...

    create104(recordType, fields, values) {
        return {
            Format: "BEJSON",
            Format_Version: "104",
            Format_Creator: "Elton Boehnen",
            Records_Type: [recordType],
            Fields: fields,
            Values: values
        };
    },

    // ... other methods ...
};

This function directly encapsulates the mandatory structure for BEJSON 104, ensuring that any document generated through it conforms to the universal requirements. This programmatic guarantee of structural compliance reduces implementation errors and simplifies data management across systems. BEJSON 104's role as the initial and most rigid BEJSON format underpins the entire ecosystem's reliability and consistency, providing a clear, unambiguous data standard where standard JSON falls short.

Chapter 3

Chapter 3: Positional Integrity and Field Mapping in BEJSON 104

The Mandate of Positional Integrity

Positional integrity in BEJSON 104 dictates a strict, one-to-one correspondence between the Fields array and each record within the Values array. Each object in Fields defines a column, and the position of that object determines the expected data type and meaning for the corresponding position in every data row in Values.

Consider a scenario where a standard JSON document might represent optional data by simply omitting a key-value pair. This approach, while flexible, leads to inconsistent object structures, requiring parsers to perform iterative key lookups or conditional checks for every piece of data. This introduces significant overhead and fragility. BEJSON 104 completely bypasses this issue. If a data point for a specific field is absent in a given record, its position must be preserved using null. This prevents any "field shifting," where the absence of a value would cause subsequent values to occupy incorrect positions, leading to data misinterpretation. This strict matrix structure is a hard validation failure if violated, ensuring that every record array always matches the Fields array length.

This design choice provides several advantages over standard JSON:

  • Predictable Access: Data can be accessed directly by index once the field map is established, eliminating the need for string key lookups per row.
  • Consistent Structure: Every record adheres to the same schema, simplifying parsing logic and reducing edge cases.
  • Optimized Performance: With fixed positions, data processing becomes highly efficient.

The lib_bejson_validator.js library explicitly enforces these rules, ensuring that all BEJSON 104 documents maintain this structural integrity from creation.

Field Mapping for O(1) Data Access

The Fields array in a BEJSON 104 document serves as its embedded, self-describing schema. Each object within Fields defines a column by its name and type. This explicit mapping is crucial for enabling the efficient O(1) data lookups mentioned in the knowledge base, a core benefit derived from BEJSON's architecture.

The lib_bejson_core.js library provides primitive operations such as bejson_core_get_field_map and bejson_core_get_field_index. These functions leverage caching to convert human-readable field names into direct numerical indices. Once cached, subsequent lookups for the same field become instantaneous, bypassing the need for iterating through schema definitions.

For instance, the bejson_cache.test.js demonstrates this mechanism:

// From bejson_cache.test.js
function test_cache_lookup() {
    console.log("Running test_cache_lookup...");
    const doc = {
        Format_Version: "104",
        Fields: [{name: "id"}, {name: "name"}, {name: "value"}],
        Values: []
    };
    
    console.assert(BEJSON.bejson_core_get_field_index(doc, "name") === 1, "Field 'name' index should be 1");
    console.assert(BEJSON.bejson_core_get_field_index(doc, "value") === 2, "Field 'value' index should be 2");
    console.assert(BEJSON.bejson_core_get_field_index(doc, "missing") === -1, "Missing field index should be -1");
}

This test confirms that bejson_core_get_field_index accurately retrieves the positional index of a field, allowing direct access to its corresponding value in any Values array row. This is a significant improvement over typical JSON parsing, where retrieving a value by its key could involve hashing or string comparisons for every access.

The lib_bejson_Core_bejson_bejson.js library also exposes this functionality:

// From lib_bejson_Core_bejson_bejson.js
BEJSON = {
    // ...
    getFieldIndex(doc, fieldName) {
        return doc.Fields.findIndex(f => f.name === fieldName);
    },

    query(doc, fieldName, value) {
        const idx = this.getFieldIndex(doc, fieldName);
        if (idx === -1) return [];
        return doc.Values.filter(row => row[idx] === value);
    }
    // ...
};

The getFieldIndex method directly leverages the Fields array to find the index, which is then used by the query method to filter records by value. This illustrates how applications within the BEJSON ecosystem perform fast, schema-aware data operations.

Furthermore, other BEJSON components, such as lib_bejson_Core_bejson_renderer.ts and lib_bejson_Utility_bejson_utility.ts, utilize dynamic field mapping to ensure compatibility and efficiency, even when dealing with documents that may have evolved over time. They explicitly call bejson_core_get_field_map to retrieve the current field-to-index mapping for a document, and then use the resulting map (e.g., fm) for data access:

// From lib_bejson_Core_bejson_renderer.ts
    let tileData: number[] = [];
    if (grid.Values && grid.Fields) {
      const doc = grid as BEJSONDocument;
      const fm = (doc as any)._bejson_field_map || ((doc as any)._bejson_field_map = bejson_core_get_field_map(doc));
      const dataIdx = fm["data"] ?? RENDERER_LEGACY.data;
      tileData = doc.Values[0][dataIdx] as number[];
    } else {
      tileData = grid.data;
    }
// From lib_bejson_Utility_bejson_utility.ts
    // Optimized Field Mapping
    const fm = bejson_core_get_field_map(dbDoc);
    const rtpIdx = fm["Record_Type_Parent"] ?? CHUNK_LEGACY.Record_Type_Parent;
    const curVerIdx = fm["current_version"] ?? CHUNK_LEGACY.current_version;

These examples highlight that the field map is either cached directly on the document (_bejson_field_map) or generated on demand via bejson_core_get_field_map, providing a robust and performant way to interact with BEJSON data.

BEJSON 104 Scheme Example

The following BEJSON 104 document UserProfiles.bejson further illustrates positional integrity and field mapping:

{
  "Format": "BEJSON",
  "Format_Version": "104",
  "Format_Creator": "Elton Boehnen",
  "Records_Type": ["UserProfile"],
  "Fields": [
    { "name": "user_id", "type": "string" },
    { "name": "username", "type": "string" },
    { "name": "email", "type": "string" },
    { "name": "is_active", "type": "boolean" },
    { "name": "last_login", "type": "string" }
  ],
  "Values": [
    ["USR-001", "alice_smith", "alice@example.com", true, "2026-07-20T10:00:00Z"],
    ["USR-002", "bob_johnson", "bob@example.com", false, null],
    ["USR-003", "charlie_brown", "charlie@example.com", true, "2026-07-21T14:30:00Z"]
  ]
}

In this document:

  • The Fields array explicitly defines five columns.
  • Each record in the Values array contains exactly five elements.
  • For USR-002, the last_login field is null, maintaining the required length and preventing data misalignment. This is the only valid mechanism for omitting data while preserving positional integrity.

This strict adherence to a columnar, matrix-like structure is the core reason BEJSON 104 was created as the first format. It directly addresses the structural ambiguities and processing inefficiencies that plague generic JSON when used for structured data, providing a foundation of reliability and consistency for the entire BEJSON ecosystem. This foundational rigidity is paramount for content management systems and data portability where predictable parsing is a strict requirement.

Chapter 4

Chapter 4: BEJSON 104's Advantages Over Standard JSON

Explicit Schema and Positional Integrity

One of BEJSON 104's foremost advantages lies in its explicit, embedded schema, manifested through the Fields array. Unlike standard JSON, where object keys and their presence can vary between records, BEJSON 104 mandates a fixed structure for all data entries within the Values array. As discussed in the previous section on positional integrity, every record in Values must align precisely with the Fields array, using null to preserve position for absent data.

This design choice eliminates the "cascade problem" inherent in loosely structured JSON, where inconsistent object shapes can lead to unpredictable application behavior and increased processing complexity. With BEJSON 104, parsers are not required to infer structure or handle varying key sets per record; they operate on a known, consistent matrix.

Consider a simple representation of user data in standard JSON:

[
  { "id": "USR-001", "name": "Alice", "email": "alice@example.com" },
  { "id": "USR-002", "name": "Bob" }, // Missing email
  { "id": "USR-003", "email": "charlie@example.com", "name": "Charlie" } // Different key order
]

This flexibility in standard JSON, while useful for certain scenarios, necessitates robust error handling and iterative key lookups. For a system processing millions of such records, this dynamic access pattern introduces significant computational overhead.

BEJSON 104, conversely, strictly enforces a consistent structure:

{
  "Format": "BEJSON",
  "Format_Version": "104",
  "Format_Creator": "Elton Boehnen",
  "Records_Type": ["User"],
  "Fields": [
    { "name": "id", "type": "string" },
    { "name": "name", "type": "string" },
    { "name": "email", "type": "string" }
  ],
  "Values": [
    ["USR-001", "Alice", "alice@example.com"],
    ["USR-002", "Bob", null],
    ["USR-003", "Charlie", "charlie@example.com"]
  ]
}

In this BEJSON 104 structure, every row in Values has three elements, corresponding directly to id, name, and email. The absence of an email for "Bob" is handled by null, maintaining the positional integrity of the data matrix.

Performance and Predictable Data Access

The strict positional integrity of BEJSON 104 enables highly optimized data access, particularly O(1) lookups once field mappings are cached. As demonstrated by the bejson_core_get_field_index function from lib_bejson_core.js, field names are quickly resolved to numerical indices. This allows direct array access (row[index]) instead of slower associative array (object key) lookups, providing a measurable performance gain for large datasets.

The lib_bejson_Core_bejson_bejson.js library explicitly provides utilities that leverage this structural advantage:

// From lib_bejson_Core_bejson_bejson.js
BEJSON = {
    // ...
    create104(recordType, fields, values) {
        return {
            Format: "BEJSON",
            Format_Version: "104",
            Format_Creator: "Elton Boehnen",
            Records_Type: [recordType],
            Fields: fields,
            Values: values
        };
    },

    getFieldIndex(doc, fieldName) {
        // Leverages the Fields array for direct index lookup
        return doc.Fields.findIndex(f => f.name === fieldName);
    },

    query(doc, fieldName, value) {
        const idx = this.getFieldIndex(doc, fieldName); // O(1) after initial cache
        if (idx === -1) return [];
        return doc.Values.filter(row => row[idx] === value); // Efficient array filtering
    }
    // ...
};

This code illustrates how BEJSON 104 facilitates efficient data creation and querying. The create104 function ensures adherence to the mandatory keys and structure from inception. The query method capitalizes on the fixed field indices to filter records directly, bypassing the need for per-row key comparisons. This is a significant advantage for applications requiring high-throughput data processing or frequent queries against large collections of records.

Readability and Portability for CMS

For content management systems (CMS) and data portability, the consistent and self-describing nature of BEJSON 104 is critical. A 104 document clearly articulates its data structure via the Fields array, making it easier for human developers to understand and for automated systems to parse and validate. This explicit structure is crucial for seamless data migrations, updates, and integrations across different platforms, ensuring that data integrity is maintained regardless of the consumption environment.

The absence of custom top-level headers in BEJSON 104, outside of the optional Parent_Hierarchy, reinforces its role as a focused single-entity store. This rigidity ensures that core data payload remains isolated from metadata concerns, which are instead managed by other BEJSON formats like 104a or orchestrated at the MFDB level. This architectural isolation is a deliberate design choice to prevent the "closet full of dropping shoes" issue associated with feature creep in data structures.

In summary, BEJSON 104 was conceived as the antidote to the structural ambiguities and processing inefficiencies of standard JSON when applied to structured, single-entity data. Its stringent requirements for positional integrity, explicit schema definition, and foundational adherence to standard primitives deliver a data format that is not only highly performant but also supremely predictable and reliable—qualities that are non-negotiable for robust software ecosystems and critical content management operations.

Chapter 5

Chapter 5: Defining Schemas with BEJSON 104's Fields Array

The Purpose of the Fields Array

The primary purpose of the Fields array is to provide an authoritative blueprint for the data. Each object within this array defines a column in the data matrix, specifying its name and type. This declarative approach removes ambiguity, enabling both human developers and automated systems to interpret the data without inference.

For BEJSON 104, the Fields array must be an array of objects, where each object contains at least a name and a type. This requirement is a foundational aspect of the BEJSON validation checklist and is enforced by lib_bejson_validator.js. The name key assigns a logical identifier to each data point, while the type key declares the expected data type for values in that column.

Consider this minimal Fields array for a User entity:

"Fields": [
  { "name": "user_id", "type": "string" },
  { "name": "username", "type": "string" },
  { "name": "email", "type": "string" },
  { "name": "is_active", "type": "boolean" },
  { "name": "login_count", "type": "integer" }
]

This schema indicates that every record in the Values array will have five positions, corresponding to user_id, username, email, is_active, and login_count, in that exact order. Each position is further constrained by its declared type.

Data Type Declaration and Validation

The type attribute within each field definition is not merely descriptive; it is prescriptive. BEJSON 104 supports full JSON types, including string, integer, number, boolean, array, and object. This explicit type declaration enables strong validation, preventing malformed data from entering the system and ensuring data integrity at the point of ingestion or modification.

For example, if login_count is declared as "type": "integer", any attempt to store a string or an array in that position would constitute a validation failure according to lib_bejson_validator.js. This mechanism directly addresses the "cascade problem" by establishing a contract for the data early in the processing pipeline.

The Fields array also dictates the expectation for null values. As detailed in the "Universal BEJSON Requirements," null must be used to preserve the matrix for any absent data; field shifting is a hard validation failure. This means if a user does not have an email, its corresponding position in the Values array must contain null, not be omitted, thus maintaining strict positional integrity.

Here is a complete BEJSON 104 document demonstrating the Fields array in practice:

{
  "Format": "BEJSON",
  "Format_Version": "104",
  "Format_Creator": "Elton Boehnen",
  "Records_Type": ["User"],
  "Fields": [
    { "name": "id", "type": "string" },
    { "name": "name", "type": "string" },
    { "name": "email", "type": "string" },
    { "name": "roles", "type": "array" },
    { "name": "profile_data", "type": "object" }
  ],
  "Values": [
    ["USR-001", "Alice", "alice@example.com", ["admin", "editor"], {"theme": "dark"}],
    ["USR-002", "Bob", null, ["viewer"], {"timezone": "GMT-5", "prefs_id_fk": "PREF-123"}],
    ["USR-003", "Charlie", "charlie@example.com", [], null]
  ]
}

In this example, roles is explicitly declared as an array, and profile_data as an object. This allows for structured, complex data within a single BEJSON 104 record while still maintaining the overall schema rigidity. The absence of profile_data for Charlie is handled with a null value, preserving the matrix.

Advantages for Predictability and Performance

The explicit schema defined by the Fields array is fundamental to achieving predictable data access and superior performance. As highlighted in the previous section, the bejson_core_get_field_index function from lib_bejson_core.js (and getFieldIndex from lib_bejson_Core_bejson_bejson.js) leverages this fixed Fields definition. It maps field names to numerical indices, allowing for O(1) direct array access rather than repeated, slower associative array lookups common in standard JSON processing.

The test_cache_lookup and test_cache_collision functions in bejson_cache.test.js specifically validate the efficiency of this field mapping, ensuring that BEJSON 104 documents consistently provide rapid index resolution. This predictability is paramount for high-throughput data operations and for reliable long-term data management, particularly in CMS environments where data integrity and consistent structure are non-negotiable.

BEJSON 104 was designed to be the foundational data standard specifically because it introduced this explicit, rigid schema via the Fields array. This concept laid the groundwork for more specialized formats like 104a and 104db, which build upon 104's core principles while introducing their own constraints. By mandating a clear schema from its inception, BEJSON 104 provided a robust alternative to standard JSON for scenarios demanding strong structural guarantees and optimized data handling.

Chapter 6

Chapter 6: Data Representation and Complex Types in BEJSON 104

Chapter 6: Data Representation and Complex Types in BEJSON 104

BEJSON 104 serves as the foundational data standard within the BEJSON ecosystem. Its primary purpose, as the initial format, was to address the structural deficiencies of standard JSON by introducing a rigid, self-describing schema, while retaining the flexibility to store complex data types. This balance makes BEJSON 104 uniquely suited for single-entity stores requiring both structural integrity and rich data representation.

The Full Spectrum of JSON Types in BEJSON 104

Unlike BEJSON 104a, which intentionally restricts data types to primitives for lightweight parsing, BEJSON 104 fully supports all native JSON types. This includes string, integer, number, boolean, array, and object structures directly within its Values matrix. This capability is critical for applications that need to embed hierarchical or multi-valued data within individual records without resorting to external linking or complex serialization.

The Fields array, as discussed in the preceding chapter, declares the expected type for each data column. For complex types, this declaration is direct:

"Fields": [
  { "name": "document_id", "type": "string" },
  { "name": "tags", "type": "array" },
  { "name": "metadata", "type": "object" },
  { "name": "nested_values", "type": "array" },
  { "name": "status_flags", "type": "object" }
]

This schema dictates that the tags field will contain an array, metadata an object, and so forth. The lib_bejson_validator.js library, which enforces BEJSON 104 structural integrity, validates these type declarations, ensuring that any value inserted into Values for these positions matches the declared complex type. An attempt to place a string where an array is expected, for instance, would result in a validation error.

Storing Complex Data: Examples

The explicit declaration of complex types within the Fields array enables direct storage of arrays and objects in the Values array. Each entry in a Values row corresponds positionally to a field in the Fields array, maintaining a strict data matrix.

Consider a BEJSON 104 document designed to store configuration settings for a software component:

{
  "Format": "BEJSON",
  "Format_Version": "104",
  "Format_Creator": "Elton Boehnen",
  "Records_Type": ["ComponentConfig"],
  "Fields": [
    { "name": "config_id", "type": "string" },
    { "name": "feature_toggles", "type": "object" },
    { "name": "allowed_users", "type": "array" },
    { "name": "log_levels", "type": "object" },
    { "name": "description", "type": "string" }
  ],
  "Values": [
    [
      "CMP-001-ALPHA",
      { "darkMode": true, "betaFeatures": ["A", "C"] },
      ["admin", "dev_team_alpha"],
      { "console": "info", "file": "debug" },
      "Configuration for the Alpha component, stable release."
    ],
    [
      "CMP-002-BETA",
      { "darkMode": false, "betaFeatures": [] },
      ["qa_team"],
      { "console": "warn", "file": "error" },
      "Configuration for the Beta component, experimental features."
    ],
    [
      "CMP-003-PROD",
      { "darkMode": true, "betaFeatures": [] },
      null,
      { "console": "error", "file": "critical" },
      "Production configuration for core services."
    ]
  ]
}

In this example:

  • feature_toggles and log_levels are object types, allowing for key-value pairs representing specific settings.
  • allowed_users is an array, useful for enumerating multiple values.
  • For "CMP-003-PROD", the allowed_users field is null, demonstrating the universal BEJSON requirement for null to preserve positional integrity when data is absent, rather than omitting the field entirely. This adheres to the "Structural Nulls" requirement of the BEJSON validation checklist.

This capability is also demonstrated in how components like lib_bejson_Gaming_bejson_renderer.js might interpret a grid object. While not explicitly showing object or array types in its Fields definition, its handling of tileData as a number[] directly within a BEJSON document implicitly relies on BEJSON 104's ability to store arrays of primitives as a single field value.

BEJSON 104's Advantages for Complex Data over Standard JSON

BEJSON 104 was created as the first format to directly address fundamental limitations of standard JSON, particularly concerning structured data and complex types:

  1. Schema Enforcement for Complex Structures: Standard JSON is schema-less by default. While JSON Schema exists, it is an external, optional layer. BEJSON 104 embeds its schema directly via the Fields array. This ensures that even complex array and object types are consistently applied across all records. The Format_Version: "104" and Records_Type keys signal this inherent structural contract, as required by the universal BEJSON requirements and enforced by lib_bejson_validator.js.
  2. Predictable Access and Reduced Inference: With field names and types pre-declared in Fields, applications reading BEJSON 104 documents do not need to infer data types or field existence. This predictability is critical for performance, as highlighted by bejson_cache.test.js validating O(1) field index lookups using bejson_core_get_field_index. When working with complex types, this means the application knows to expect an array or an object at a specific index, simplifying parsing logic and reducing runtime errors.
  3. Strict Positional Integrity: The mandate for null padding in BEJSON 104, even for complex types, guarantees that the data matrix remains consistent. If an object or array is optional for a record, its position must be null, not omitted. This prevents "field shifting," a common issue in flexible JSON structures, and ensures that Values arrays always align precisely with the Fields array. This is a hard validation failure if violated.
  4. Architectural Isolation: By defining a complete, self-contained schema for its content, BEJSON 104 documents can operate with architectural isolation. This means a BEJSON 104 file, even with complex nested data, can be parsed and validated independently without relying on external schema definitions or database metadata. This characteristic was a primary driver for its creation and makes it highly portable across CMS environments.

BEJSON 104 was developed to provide this robust, schema-driven approach to data representation from its inception. It laid the groundwork for the entire BEJSON ecosystem by demonstrating that structured data could be both flexible enough for complex types and rigid enough for guaranteed integrity.

Chapter 7

Chapter 7: Practical Application: Creating and Manipulating BEJSON 104 Documents

The Necessity of BEJSON 104 and Its Foundational Role

Before the introduction of BEJSON 104, developers using standard JSON faced challenges in ensuring data consistency and reliable programmatic access, particularly in content management systems or configurations where data integrity was paramount. Standard JSON, while flexible, lacks built-in mechanisms for schema enforcement or mandatory field definitions, leading to brittle systems susceptible to runtime errors from missing or inconsistently typed data.

BEJSON 104 solved these issues by embedding its schema directly within the document via the Fields array. This self-describing nature, combined with strict validation rules enforced by lib_bejson_validator.js and lib_bejson_core.js, ensures that every BEJSON 104 document adheres to a predictable structure. It serves as the bedrock for more specialized BEJSON formats like 104a and 104db, demonstrating how a rigid data matrix can coexist with the flexibility of JSON. Its explicit design prevents common data corruption issues that plague schema-less JSON implementations.

Creating a BEJSON 104 Document

Creating a BEJSON 104 document involves defining its core structural components: Format, Format_Version, Format_Creator, Records_Type, Fields, and Values. As established by universal BEJSON requirements, these six top-level keys are mandatory.

The lib_bejson_Core_bejson_bejson.js library provides a create104 utility function designed to simplify this process:

// Example using BEJSON.create104 from lib_bejson_Core_bejson_bejson.js
const BEJSON = require('./lib_bejson_Core_bejson_bejson.js'); // In a Node.js environment

// Define the fields for our records
const productFields = [
    { name: "product_id", type: "string" },
    { name: "name", type: "string" },
    { name: "category", type: "string" },
    { name: "price", type: "number" },
    { name: "available_sizes", type: "array" }, // As discussed in Chapter 6
    { name: "details", type: "object" }         // As discussed in Chapter 6
];

// Define the initial values for the records
const productValues = [
    [
        "PROD-001",
        "Wireless Mouse",
        "Peripherals",
        29.99,
        ["S", "M"],
        { "weight_g": 85, "color": "black" }
    ],
    [
        "PROD-002",
        "Mechanical Keyboard",
        "Peripherals",
        89.50,
        null, // No sizes apply, null preserves positional integrity
        { "layout": "US_ANSI", "backlit": true }
    ]
];

// Create the BEJSON 104 document
const productCatalog = BEJSON.create104(
    "Product",      // The single record type for 104
    productFields,
    productValues
);

console.log(JSON.stringify(productCatalog, null, 2));

This code generates a BEJSON 104 document adhering to all structural requirements:

{
  "Format": "BEJSON",
  "Format_Version": "104",
  "Format_Creator": "Elton Boehnen",
  "Records_Type": ["Product"],
  "Fields": [
    { "name": "product_id", "type": "string" },
    { "name": "name", "type": "string" },
    { "name": "category", "type": "string" },
    { "name": "price", "type": "number" },
    { "name": "available_sizes", "type": "array" },
    { "name": "details", "type": "object" }
  ],
  "Values": [
    [
      "PROD-001",
      "Wireless Mouse",
      "Peripherals",
      29.99,
      ["S", "M"],
      { "weight_g": 85, "color": "black" }
    ],
    [
      "PROD-002",
      "Mechanical Keyboard",
      "Peripherals",
      89.50,
      null,
      { "layout": "US_ANSI", "backlit": true }
    ]
  ]
}

Notice the use of null for available_sizes in "PROD-002". This adheres to the "Structural Nulls" requirement: null must be used to preserve the matrix for any absent data; field shifting is a hard validation failure. This ensures that the length of every array in Values exactly matches the length of the Fields array.

Manipulating BEJSON 104 Data

Manipulating BEJSON 104 data primarily involves interacting with the Values array, guided by the Fields definition. The predictability offered by the Fields array and positional integrity is a core advantage.

1. Accessing Data

Retrieving data from a BEJSON 104 document is highly efficient due to its structured nature. The lib_bejson_Core_bejson_bejson.js library provides getFieldIndex and query methods to facilitate this. The bejson_core_get_field_index (as shown in bejson_cache.test.js) provides O(1) lookups via caching, critical for performance in larger datasets.

// Accessing data from the productCatalog document
const BEJSON = require('./lib_bejson_Core_bejson_bejson.js');

// Assume productCatalog is the BEJSON 104 document created previously

// Get the index of a specific field
const nameIndex = BEJSON.getFieldIndex(productCatalog, "name");
console.log(`Index of 'name' field: ${nameIndex}`); // Output: Index of 'name' field: 1

// Query for records matching a specific field value
const peripherals = BEJSON.query(productCatalog, "category", "Peripherals");
console.log("Peripherals Found:", peripherals.length); // Output: Peripherals Found: 2

// Access data for a specific product
const firstProductRow = productCatalog.Values[0];
if (nameIndex !== -1) {
    console.log(`First product name: ${firstProductRow[nameIndex]}`); // Output: First product name: Wireless Mouse
}

// Access complex type data
const detailsIndex = BEJSON.getFieldIndex(productCatalog, "details");
if (detailsIndex !== -1) {
    const firstProductDetails = firstProductRow[detailsIndex];
    console.log(`First product color: ${firstProductDetails.color}`); // Output: First product color: black
}
2. Updating Data

Updating values requires knowing the field index and the record row. Positional integrity must be maintained; changing a value requires replacing it at its specific [row][index] coordinate.

// Updating data in the productCatalog document
const BEJSON = require('./lib_bejson_Core_bejson_bejson.js');

// Assume productCatalog is the BEJSON 104 document

const priceIndex = BEJSON.getFieldIndex(productCatalog, "price");
const idIndex = BEJSON.getFieldIndex(productCatalog, "product_id");

// Find "PROD-001" and update its price
productCatalog.Values.forEach(row => {
    if (row[idIndex] === "PROD-001") {
        row[priceIndex] = 34.99; // Update price
    }
});

console.log("Updated Product 1 Price:", productCatalog.Values[0][priceIndex]); // Output: Updated Product 1 Price: 34.99
3. Adding and Deleting Records

New records are appended to the Values array. When adding, ensure the new array row strictly matches the Fields array in length and type, using null for absent data. Deleting records involves removing rows from the Values array.

// Adding a new record
const newProduct = [
    "PROD-003",
    "Monitor Arm",
    "Accessories",
    55.00,
    null,
    { "material": "aluminum", "max_weight_kg": 9 }
];
productCatalog.Values.push(newProduct);
console.log("Total products after adding:", productCatalog.Values.length); // Output: Total products after adding: 3

// Deleting a record (e.g., "PROD-002")
const updatedValues = productCatalog.Values.filter(row => row[idIndex] !== "PROD-002");
productCatalog.Values = updatedValues;
console.log("Total products after deleting:", productCatalog.Values.length); // Output: Total products after deleting: 2

BEJSON 104's Advantages in Practical Application over Standard JSON

The practical application of BEJSON 104 documents highlights its direct advantages over unstructured JSON:

  1. Guaranteed Schema Adherence: Unlike standard JSON, where an application must infer the structure or rely on an external schema, BEJSON 104 enforces its schema within the document itself. This is evident in the Fields array defining name and type for every column, ensuring programmatic consistency across all records. The lib_bejson_validator.js ensures this contract is maintained throughout the document's lifecycle.
  2. Predictable Data Access: With a defined Fields array, applications can always determine the position (index) of any field. This eliminates the need for expensive key lookups within each record object, as demonstrated by the O(1) performance of bejson_core_get_field_index (from lib_bejson_core.js, tested in bejson_cache.test.js). This predictability is fundamental for efficient manipulation and reduces boilerplate code for error handling due to missing keys.
  3. Enforced Positional Integrity: The universal requirement for null padding in BEJSON 104 for absent data, rather than omission, prevents "field shifting." In practical terms, this means that an application can reliably access row[index] without concern that the data for that field has shifted due to a previous field being omitted in another record. This structural rigidity is a hard validation requirement.
  4. Simplified Complex Type Handling: As noted in Chapter 6, BEJSON 104's explicit type declarations for array and object in Fields simplify how applications process complex data. Developers know precisely what data structure to expect at a given index, removing ambiguity and reducing type-checking overhead that is common with raw JSON.
  5. Architectural Isolation: A BEJSON 104 file is entirely self-contained, including its schema. This makes it highly portable and ensures that data integrity can be validated and manipulated without external dependencies, critical for robust CMS portability and data exchange scenarios.

BEJSON 104's design ensures that data creation and manipulation are both predictable and efficient. Its structured approach directly mitigates the common pitfalls of schema-less JSON, establishing a reliable foundation for data management within the BEJSON ecosystem.

Chapter 8

Chapter 8: The Enduring Necessity and Role of BEJSON 104

Why BEJSON 104 Endures: Advantages over Standard JSON

BEJSON 104's design philosophy offers several enduring advantages that ensure its continued necessity in structured data applications:

  1. In-Document Schema Enforcement: Unlike standard JSON, which requires external schema definitions (e.g., JSON Schema) or implicit understanding, BEJSON 104 embeds its schema directly within the Fields array. This makes every BEJSON 104 document self-describing and self-validating. The Fields array dictates the name and type for each data point, providing an unambiguous contract for consumers. The lib_bejson_validator.js library explicitly enforces these structural and type constraints, ensuring that documents adhere to their declared schema without external lookup.

  2. Guaranteed Positional Integrity: The most fundamental difference from plain JSON objects is BEJSON 104's commitment to a data matrix via its Values array. As stated in the universal requirements, "the length of every array in Values must exactly match the length of the Fields array," and "null must be used to preserve the matrix for any absent data; field shifting is a hard validation failure." This rigid structure guarantees that the data for a given field name will always be found at its corresponding index in every record. This eliminates the "cascade problem" of data access that plagues loosely structured JSON, where fields might be entirely absent from some records, necessitating defensive coding at every access point.

  3. Predictable and Efficient Data Access: The defined Fields array allows for highly efficient data access. The lib_bejson_core.js library, specifically its bejson_core_get_field_index function, provides O(1) (constant time) lookups for field indices through caching, as evidenced by bejson_cache.test.js. This contrasts sharply with standard JSON, where accessing a property by name typically involves iterating through object keys, which becomes a performance bottleneck in large datasets. With BEJSON 104, once an index is known, accessing data becomes a direct array lookup, as demonstrated in the prior chapter's section on "Manipulating BEJSON 104 Data."

  4. Robust Handling of Complex Types: BEJSON 104 fully supports native JSON types, including complex array and object structures. By declaring these types in the Fields array, developers gain explicit knowledge of the expected data shape. This removes ambiguity and simplifies deserialization and manipulation logic, as applications do not need to infer or extensively validate the structure of nested data.

  5. Architectural Isolation and Portability: A BEJSON 104 document is architecturally isolated; it carries all necessary information for its interpretation and validation internally. This self-containment makes it exceptionally portable for data exchange and content management systems (CMS). Data can be moved, stored, and retrieved without relying on external configuration files or database schemas, significantly reducing integration complexity and increasing system resilience.

BEJSON 104 Scheme Example

Consider a simple BEJSON 104 document defining user profiles:

{
  "Format": "BEJSON",
  "Format_Version": "104",
  "Format_Creator": "Elton Boehnen",
  "Records_Type": ["User"],
  "Fields": [
    { "name": "user_id", "type": "string" },
    { "name": "username", "type": "string" },
    { "name": "email", "type": "string" },
    { "name": "is_active", "type": "boolean" },
    { "name": "roles", "type": "array" },
    { "name": "preferences", "type": "object" }
  ],
  "Values": [
    [
      "USR-001",
      "johndoe",
      "john.doe@example.com",
      true,
      ["admin", "editor"],
      { "theme": "dark", "notifications": true }
    ],
    [
      "USR-002",
      "janesmith",
      "jane.smith@example.com",
      false,
      ["viewer"],
      { "theme": "light", "notifications": false }
    ],
    [
      "USR-003",
      "peterm",
      "peter.m@example.com",
      true,
      null,
      null
    ]
  ]
}

In this example, Records_Type contains a single string ["User"], adhering to BEJSON 104 requirements. The Fields array clearly defines six fields with their respective types. Notice how USR-003 utilizes null for roles and preferences, maintaining the strict positional integrity of the Values array. Any application processing this document can deterministically know that user_id is always at index 0, username at index 1, and so forth, without needing to check for field existence in each row.

Code Example: Robust Field Access and Validation

The programmatic interaction with BEJSON 104 documents leverages its inherent structure for reliability. The lib_bejson_Core_bejson_bejson.js utility, which encapsulates core operations, demonstrates this.

const BEJSON = require('./lib_bejson_Core_bejson_bejson.js');
const { validate104 } = require('./lib_bejson_Core_bejson_validators.js'); // For validation

const userDoc = { /* ... (the BEJSON 104 document shown above) ... */ };

// 1. Validate the document for structural integrity
try {
    validate104(userDoc);
    console.log("BEJSON 104 document is valid.");
} catch (error) {
    console.error("Validation Error:", error.message);
    // This highlights the early detection of issues before processing
    process.exit(1);
}

// 2. Efficiently get field indices using lib_bejson_core's caching (via BEJSON.getFieldIndex)
const usernameIndex = BEJSON.getFieldIndex(userDoc, "username");
const rolesIndex = BEJSON.getFieldIndex(userDoc, "roles");
const preferencesIndex = BEJSON.getFieldIndex(userDoc, "preferences");

if (usernameIndex === -1 || rolesIndex === -1 || preferencesIndex === -1) {
    console.error("Critical fields not found in schema.");
    process.exit(1);
}

// 3. Process records with guaranteed positional access
userDoc.Values.forEach((record, i) => {
    const username = record[usernameIndex];
    const roles = record[rolesIndex];
    const preferences = record[preferencesIndex];

    console.log(`\nUser ${i + 1}: ${username}`);
    console.log(`  Roles: ${roles ? roles.join(', ') : 'No roles assigned (null)'}`);
    console.log(`  Preferences: ${preferences ? JSON.stringify(preferences) : 'No preferences (null)'}`);

    // Demonstrate access to complex types
    if (preferences && typeof preferences === 'object' && preferences.theme) {
        console.log(`  Theme: ${preferences.theme}`);
    }
});

// 4. Update data with positional certainty
const emailIndex = BEJSON.getFieldIndex(userDoc, "email");
userDoc.Values[0][emailIndex] = "john.doe.updated@example.com";
console.log(`\nUpdated email for ${userDoc.Values[0][usernameIndex]}: ${userDoc.Values[0][emailIndex]}`);

This code explicitly calls validate104 from lib_bejson_Core_bejson_validators.js to confirm the document's adherence to the BEJSON 104 standard before any data processing. This preemptive validation prevents runtime errors that would occur if, for instance, a Values row had an incorrect length or a mandatory key was missing. Subsequently, field indices are retrieved once and then used for all data access, demonstrating the performance benefits of positional integrity and O(1) lookups provided by bejson_core_get_field_index.

BEJSON 104, as the inaugural BEJSON standard, provides an indispensable foundation for structured data management. Its strict validation rules, self-describing schema, and commitment to positional integrity directly address the chaos inherent in unstructured data, enabling robust, maintainable, and predictable data interaction across diverse applications. Its principles were critical in paving the way for more complex formats while remaining a vital and direct solution for single-entity data storage.