# `nupp.codec.json.spi` ## Types ### `EncodedString` _record_ ```nupp record EncodedString ``` A JSON string whose immutable encoded bytes have already been produced or validated. `Writer:key` accepts this type without validating UTF-8 or escaping it again. Values produced by `encodedString` and `verifiedString` are interned. ### `EncodedValue` _record_ ```nupp record EncodedValue ``` A complete JSON value whose immutable bytes have already been encoded or validated. Values come from `encoded` or `verified`; the private token prevents checked callers from manufacturing an unverified fast-path value. ### `JSONEncodable` _interface_ ```nupp interface JSONEncodable ... ``` Values that can write one complete JSON value through a checked writer. `nupp.codec.json` names it for callers; it is declared here so the modules the facade reads, nupp.serde and nupp.derive among them, can name it without reading the facade. `Writer` below names the encoder `newWriter()` returns. ```nupp local record Money is nupp.codec.json.JSONEncodable cents: integer function writeJSON(self, exclusive out: nupp.codec.json.Writer): nil out:startObject():key("cents"):write(self.cents):endObject() end end ``` #### Members | Name | Kind | Description | | --- | --- | --- | | [`writeJSON`](#nupp.codec.json.spi.JSONEncodable.writeJSON) | method | Writes this value at the writer's current value position. | #### `writeJSON` _method_ ```nupp writeJSON: function(self, exclusive out: Writer): nil ``` Writes this value at the writer's current value position. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `?` | `self` | | | `exclusive out` | `Writer` | the checked destination | ##### Returns | Type | Description | | --- | --- | | `nil` | | ### `MarkContainer` _type_ ```nupp type MarkContainer = function(takes value: T): T preserves value ``` Marks a table while returning the same generic table and ownership. The takes/preserves relation is intentional: an implementation must not copy the container or erase an affine owner while applying its JSON marker. ### `Provider` _interface_ ```nupp interface Provider ... ``` JSON API 2, including portable encoding and optional compiled serde. Arrays, objects, null sentinels, and verified fragments must agree across every member of this table. Keep marker identities stable for the loaded provider. The caller's nullValue controls null conversion; omission follows the public JSON API's nil behavior. Reject malformed syntax, invalid UTF-8, unsupported container shapes, and invalid raw fragments according to that API. The three serde hooks are optional accelerators. If supplied together, compiled schemas and both decode entry points must share their representation and unknown-member policy. All buffer operations use the canonical shared Buffer; they must preserve the declared exclusive access and ownership guarantees. #### Members | Name | Kind | Description | | --- | --- | --- | | [`priority`](#nupp.codec.json.spi.Provider.priority) | field | | | [`arrayOf`](#nupp.codec.json.spi.Provider.arrayOf) | method | Builds an array projection shape with the supplied element shape. | | [`asArray`](#nupp.codec.json.spi.Provider.asArray) | field | Marks and returns the same table as an array, preserving its ownership. | | [`asObject`](#nupp.codec.json.spi.Provider.asObject) | field | Marks and returns the same table as an object, preserving its ownership. | | [`isArray`](#nupp.codec.json.spi.Provider.isArray) | method | Reports whether a value has JSON array semantics. | | [`decode`](#nupp.codec.json.spi.Provider.decode) | method | Parses JSON, applying the caller-selected representation of null. | | [`encode`](#nupp.codec.json.spi.Provider.encode) | method | Serializes a value with this provider's markers and null convention. | | [`encoded`](#nupp.codec.json.spi.Provider.encoded) | method | Creates a validated encoded-value fragment for subsequent composition. | | [`encodedString`](#nupp.codec.json.spi.Provider.encodedString) | method | Creates a fragment containing one escaped JSON string. | | [`pull`](#nupp.codec.json.spi.Provider.pull) | method | Parses only the value projection described by shape. | | [`verified`](#nupp.codec.json.spi.Provider.verified) | method | Validates raw JSON and retains a fragment suitable for composition. | | [`verifiedString`](#nupp.codec.json.spi.Provider.verifiedString) | method | Validates a raw encoded JSON string fragment. | | [`newWriter`](#nupp.codec.json.spi.Provider.newWriter) | method | Creates a JSON writer over exclusive access to the canonical buffer. | | [`NULL`](#nupp.codec.json.spi.Provider.NULL) | field | Stable explicit null marker owned by this loaded implementation. | | [`EMPTY\_ARRAY`](#nupp.codec.json.spi.Provider.EMPTY_ARRAY) | field | Stable empty-array marker value. | | [`EMPTY\_OBJECT`](#nupp.codec.json.spi.Provider.EMPTY_OBJECT) | field | Stable empty-object marker value. | | [`compileSerde`](#nupp.codec.json.spi.Provider.compileSerde) | field | Optionally prepares a schema plan with its unknown-member policy. | | [`decodeSerde`](#nupp.codec.json.spi.Provider.decodeSerde) | field | Optionally decodes a prepared schema, returning value or diagnostic. | | [`decodeSerdeBuffer`](#nupp.codec.json.spi.Provider.decodeSerdeBuffer) | field | Optionally decodes from exclusive access to the canonical buffer. | #### `priority` _field_ ```nupp priority: integer? ``` `@readonly` #### `arrayOf` _method_ ```nupp arrayOf: function(shape: any?): any ``` `@readonly` Builds an array projection shape with the supplied element shape. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `shape` | `any?` | | ##### Returns | Type | Description | | --- | --- | | `any` | | #### `asArray` _field_ ```nupp asArray: MarkContainer ``` `@readonly` Marks and returns the same table as an array, preserving its ownership. #### `asObject` _field_ ```nupp asObject: MarkContainer ``` `@readonly` Marks and returns the same table as an object, preserving its ownership. #### `isArray` _method_ ```nupp isArray: function(value: any): boolean ``` `@readonly` Reports whether a value has JSON array semantics. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `value` | `any` | | ##### Returns | Type | Description | | --- | --- | | `boolean` | | #### `decode` _method_ ```nupp decode: function(text: string, nullValue: any?): any ``` `@readonly` Parses JSON, applying the caller-selected representation of null. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `text` | `string` | | | `nullValue` | `any?` | | ##### Returns | Type | Description | | --- | --- | | `any` | | #### `encode` _method_ ```nupp encode: function(value: any, nullValue: any?): string ``` `@readonly` Serializes a value with this provider's markers and null convention. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `value` | `any` | | | `nullValue` | `any?` | | ##### Returns | Type | Description | | --- | --- | | `string` | | #### `encoded` _method_ ```nupp encoded: function(value: any, nullValue: any?): any ``` `@readonly` Creates a validated encoded-value fragment for subsequent composition. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `value` | `any` | | | `nullValue` | `any?` | | ##### Returns | Type | Description | | --- | --- | | `any` | | #### `encodedString` _method_ ```nupp encodedString: function(value: string): any ``` `@readonly` Creates a fragment containing one escaped JSON string. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `value` | `string` | | ##### Returns | Type | Description | | --- | --- | | `any` | | #### `pull` _method_ ```nupp pull: function(text: string, shape: any, nullValue: any?): any ``` `@readonly` Parses only the value projection described by shape. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `text` | `string` | | | `shape` | `any` | | | `nullValue` | `any?` | | ##### Returns | Type | Description | | --- | --- | | `any` | | #### `verified` _method_ ```nupp verified: function(text: string): any ``` `@readonly` Validates raw JSON and retains a fragment suitable for composition. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `text` | `string` | | ##### Returns | Type | Description | | --- | --- | | `any` | | #### `verifiedString` _method_ ```nupp verifiedString: function(text: string): any ``` `@readonly` Validates a raw encoded JSON string fragment. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `text` | `string` | | ##### Returns | Type | Description | | --- | --- | | `any` | | #### `newWriter` _method_ ```nupp newWriter: function(exclusive out: SharedBuffer, nullValue: any?): any ``` `@readonly` Creates a JSON writer over exclusive access to the canonical buffer. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive out` | `SharedBuffer` | | | `nullValue` | `any?` | | ##### Returns | Type | Description | | --- | --- | | `any` | | #### `NULL` _field_ ```nupp NULL: any ``` `@readonly` Stable explicit null marker owned by this loaded implementation. #### `EMPTY_ARRAY` _field_ ```nupp EMPTY_ARRAY: table ``` `@readonly` Stable empty-array marker value. #### `EMPTY_OBJECT` _field_ ```nupp EMPTY_OBJECT: table ``` `@readonly` Stable empty-object marker value. #### `compileSerde` _field_ ```nupp compileSerde: (function(plan: any, unknownMembers: string): any)? ``` `@readonly` Optionally prepares a schema plan with its unknown-member policy. #### `decodeSerde` _field_ ```nupp decodeSerde: (function(schema: any, text: string): (any?, string?))? ``` `@readonly` Optionally decodes a prepared schema, returning value or diagnostic. #### `decodeSerdeBuffer` _field_ ```nupp decodeSerdeBuffer: (function(schema: any, exclusive input: SharedBuffer): (any?, string?))? ``` `@readonly` Optionally decodes from exclusive access to the canonical buffer. ### `Writer` _interface_ ```nupp interface Writer is nupp.Closeable ... ``` A checked incremental JSON writer. ```nupp local out = nupp.text.newBuffer() local writer = nupp.codec.json.newWriter(out) writer:startObject():key("ok"):write(true):endObject() writer:close() assert(out:tostring() == [[{"ok":true}]]) ``` #### Members | Name | Kind | Description | | --- | --- | --- | | [`startArray`](#nupp.codec.json.spi.Writer.startArray) | method | Starts an array value. | | [`startObject`](#nupp.codec.json.spi.Writer.startObject) | method | Starts an object value. | | [`key`](#nupp.codec.json.spi.Writer.key) | method | Selects the next object member. | | [`write`](#nupp.codec.json.spi.Writer.write) | method | Appends one complete Lua value. | | [`null`](#nupp.codec.json.spi.Writer.null) | method | Appends JSON null. | | [`endArray`](#nupp.codec.json.spi.Writer.endArray) | method | Ends the current array. | | [`endObject`](#nupp.codec.json.spi.Writer.endObject) | method | Ends the current object. | | [`flush`](#nupp.codec.json.spi.Writer.flush) | method | Publishes staged bytes without ending the document. | | [`close`](#nupp.codec.json.spi.Writer.close) | method | Verifies and publishes one complete root, then releases backing state. | #### `startArray` _method_ ```nupp startArray: function(exclusive self: Writer): Writer borrows (self) ``` Starts an array value. ```nupp local out = nupp.text.newBuffer() local writer = nupp.codec.json.newWriter(out) writer:startArray():write("first"):endArray() writer:close() assert(out:tostring() == "[\"first\"]") ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `Writer` | the writer | ##### Returns | Type | Description | | --- | --- | | `Writer borrows (self)` | this writer | #### `startObject` _method_ ```nupp startObject: function(exclusive self: Writer): Writer borrows (self) ``` Starts an object value. ```nupp local out = nupp.text.newBuffer() local writer = nupp.codec.json.newWriter(out) writer:startObject():endObject() writer:close() assert(out:tostring() == "{}") ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `Writer` | the writer | ##### Returns | Type | Description | | --- | --- | | `Writer borrows (self)` | this writer | #### `key` _method_ ```nupp key: function(exclusive self: Writer, name: string): Writer borrows (self) & function(exclusive self: Writer, name: EncodedString): Writer borrows (self) ``` Selects the next object member. ```nupp local out = nupp.text.newBuffer() local writer = nupp.codec.json.newWriter(out) writer:startObject():key("answer"):write(42):endObject() writer:close() assert(out:tostring() == [[{"answer":42}]]) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `Writer` | the writer | | `name` | `string` | the next member name | ##### Returns | Type | Description | | --- | --- | | `Writer borrows (self)` | this writer | #### `write` _method_ ```nupp write: function( exclusive self: Writer, value: string | number | boolean | {any} | {[string]: any} ): Writer borrows (self) & function( exclusive self: Writer, value: EncodedValue | EncodedString ): Writer borrows (self) ``` Appends one complete Lua value. ```nupp local out = nupp.text.newBuffer() local writer = nupp.codec.json.newWriter(out) writer:startArray():write({id = 41}):endArray() writer:close() assert(out:tostring() == "[{\"id\":41}]") ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `Writer` | the writer | | `value` | `string | number | boolean | {any} | {\[string\]: any}` | the next JSON value | ##### Returns | Type | Description | | --- | --- | | `Writer borrows (self)` | this writer | #### `null` _method_ ```nupp null: function(exclusive self: Writer): Writer borrows (self) ``` Appends JSON null. ```nupp local out = nupp.text.newBuffer() local writer = nupp.codec.json.newWriter(out) writer:startArray():null():endArray() writer:close() assert(out:tostring() == "[null]") ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `Writer` | the writer | ##### Returns | Type | Description | | --- | --- | | `Writer borrows (self)` | this writer | #### `endArray` _method_ ```nupp endArray: function(exclusive self: Writer): Writer borrows (self) ``` Ends the current array. ```nupp local out = nupp.text.newBuffer() local writer = nupp.codec.json.newWriter(out) writer:startArray():startObject():endObject():endArray() writer:close() assert(out:tostring() == "[{}]") ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `Writer` | the writer | ##### Returns | Type | Description | | --- | --- | | `Writer borrows (self)` | this writer | #### `endObject` _method_ ```nupp endObject: function(exclusive self: Writer): Writer borrows (self) ``` Ends the current object. ```nupp local out = nupp.text.newBuffer() local writer = nupp.codec.json.newWriter(out) writer:startObject():key("items"):startArray():endArray():endObject() writer:close() assert(out:tostring() == [[{"items":[]}]]) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `Writer` | the writer | ##### Returns | Type | Description | | --- | --- | | `Writer borrows (self)` | this writer | #### `flush` _method_ ```nupp flush: @nosuspend function(exclusive self: Writer): nil ``` Publishes staged bytes without ending the document. ```nupp local out = nupp.text.newBuffer() local writer = nupp.codec.json.newWriter(out) writer:startArray():write(1) writer:flush() assert(out:tostring() == "[1") writer:endArray() writer:close() assert(out:tostring() == "[1]") ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `Writer` | the writer | ##### Returns | Type | Description | | --- | --- | | `nil` | | #### `close` _method_ ```nupp close: @nosuspend function(takes self: Writer): nil ``` Verifies and publishes one complete root, then releases backing state. ```nupp local out = nupp.text.newBuffer() local writer = nupp.codec.json.newWriter(out) writer:write({ok = true}) writer:close() assert(out:tostring() == [[{"ok":true}]]) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `takes self` | `Writer` | the writer | ##### Returns | Type | Description | | --- | --- | | `nil` | |