Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The Internet Object serialization format aims to redefine data interchange on the internet by addressing key challenges and limitations present in existing formats.
The inception of the Internet Object began as a side project aimed at addressing the limitations observed in the JSON format. Over time, it evolved into an independent research endeavor, focusing on effectively tackling data-transfer challenges such as size, schema validation, data streaming, header, and metadata support, among others. The design of the Internet Object format revolves around the following key objectives:
To optimize the format for internet wire transfer, the Internet Object must be conceived and developed without being excessively influenced by existing mechanisms. However, it may draw inspiration from other formats as needed.
Human Friendly
Internet Object documents must be text-based, human-friendly, and easy to work with. Developers should be able to write these documents using plain text IDEs without needing any frameworks, libraries, or utilities.
To ensure a small footprint, the Internet Object format should separate data and schema, allowing data to be sent alone over the network.
Schema First
To uphold data integrity during wire transfer, the Internet Object format should prioritize a schema-first approach.
Embracing a comprehensive document-oriented approach, the Internet Object format should facilitate the bundling of all essential components - including records, data, definitions, schemas, and comments - within a single document. This approach ensures that all related information is conveniently stored together, promoting the efficient organization and streamlined management of data and its associated elements. Moreover, it enhances maintainability and simplifies collaboration among team members, as they can easily access and understand the complete context within a single, unified document.
Complex Data Types
The Internet Object must support complex data types so that any kind of data whether large number or complex data structure can be easily serialized and deserialized for the wire.
Streaming Friendly
The Internet Object format should support the streaming of independent records, allowing for efficient and continuous data transfer. With this feature, the failure of a single record will not affect the processing of other records, ensuring more resilient data transmission.
Platform and Language independence
The Internet Object format should be designed to work seamlessly across different platforms, operating systems, and programming languages. This universal compatibility ensures broad adoption and versatility, enabling developers to easily integrate the format into their projects without limitations.
Comments
By providing support for inline comments, the Internet Object format allows users to document schemas and definitions directly within the data itself. This feature enhances readability and maintainability, making it easier for users to understand and manage complex data structures.
To increase the format's adaptability, the Internet Object should promote reusability through concepts like references and variables. This dynamic feature allows for the customization of data structures and enables users to manipulate data more effectively, catering to various needs and scenarios.
Thin, schema-first and robust data-interchange object format for Internet
This document aims to provide the Internet Object 1.0 specification and showcase various aspects of the subject.
Author and Researcher
Mohamed Aamir Maniar at ManiarTech® Lab
Contact
Version
1.0 Draft
Status
Work-in-Progress
Draft
Website
Docs
Last Updated
14th July 2025
Internet object specifies email
, url
, datetime
, date
and time
as derived types of string and also provides built-in support for them.
The following snippet represents a string and its derived types.
# Strings and its derived types
{
name: string,
emailId: email,
profileUrl: url,
journyDate: date,
departureTime: time,
bookingDatetime: datetime
}
---
{
Christopher Andrews, # string
[email protected], # email
https://www.abc.com/in/christopher-andrew-06528b155 #url
2021-02-09 # date
06:30:00 # time
2020-12-30T12:39:48.545 #datetime
}
Here the, name
is of string type and will only accept strings. Similarly, emailId
, profileUrl
, journyDate
departureTime
and bookingDatetimedate
are of different types such as email
, url
, date
, time
, datetime
. Therefore they will only accept values with the defined types for the respective variable.
Internet Object supports single-line comments for documenting and annotating data. Comments start with a hash sign (#
) and continue to the end of the line.
Start Character: Hash sign (#
U+0023)
Scope: Single line only
Placement: Can appear anywhere in the document
Content: Everything after #
on the same line is ignored by the parser
Comments can appear on any line
Can be standalone or inline after data
Support full Unicode text
Cannot span multiple lines
No special escaping needed
Be Clear and Concise: Use simple, direct language
Explain Why, Not What: Focus on reasoning rather than obvious facts
Keep Comments Updated: Update comments when data structures change
Use Consistently: Maintain uniform style throughout documents
- Overall document structure
- Unicode support in text content
When a variable is classified as an int32
type in the schema then it will be classified as an integer with a size of 32 bits or 4 bytes. The range of values is from -2,147,483,648
to 2,147,483,647
.
The int32
is derived from the number type that shares the sameas the Number i.e type
, default
, choices
, max
, min
, multipleOf
, divisibleBy
, optional
and null
while enforcing the additional constraint that the number must be of int32
type.
By default the max
value of byte
type variable is 2,147,483,647
and and min
is -2,147,483,648
.
When a variable is classified as a byte
then the data will be accepted only if it is an integer with the size of a byte or 8 bits. A byte may have, decimal, hexadecimal, octal or binary values. The range of values is from -127
to +128
.
The byte
is derived from the number type that shares the sameas the Number i.e type
, default
, choices
, max
, min
, multipleOf
, divisibleBy
, optional
and null
while enforcing the additional constraint that the number must be of byte type.
By default the max
value of byte
type variable is 128
and and min
is -127
.
# Internet Object Document: Personnel Records
# Address schema definition
~ $address: {street:string, zip:{string, maxLength:5}, city:string}
# Person schema definition
~ $schema: {
name:string, # Individual's full name
age:int, # Age in years
homeAddress?: $address, # Optional home address
officeAddress?: $address # Optional office address
}
---
# Personnel Records
~ John Doe, 25, {Queens, 50010, NewYork}, {Bond Street, 50001, NewYork}
~ Jane Doe, 20, {Queens, 50010, NewYork}, {Bond Street, 50001, NewYork}
# Person data with comments
{
# Person details
name: John Doe, # Inline field comment
age: 30, # Another inline comment
# Contact information
contact: {
email: '[email protected]',
phone: '+1-555-0123'
}
}
# int32 type variable
# only accepts inputs in the range -2147483648 to +2147483647
Test_number: {type: int32}
---
~ 100567 # valid
~ 2147483647 # valid
~ -2147483647 # valid
~ -2147483650 # invalid
~ 8222353666 # invalid
# Byte type variable
testNumber: byte
---
~ 100
~ -120
~ 0xFF # Hexadecimal Representation
~ 0b01111111 # Binary Representation
~ 0c111 # Octal Representation
Special characters are used in conjunction with structural characters and literals to provide additional functionality or context within an Internet Object document. These characters have specific semantic meanings and modify the behavior of schemas, values, or parsing.
@
At Sign
U+0040
Variable
When prefixed to a key name, declares a variable reference
$
Dollar Sign
U+0024
Schema
When prefixed to a key name, declares a schema reference
?
Question Mark
U+003F
Schema
Shortcut for declaring optional member when suffixed to the key name in object schema
*
Asterisk
U+002A
Schema
Shortcut for declaring nullable member when suffixed to the key name in object schema. Also used to make schema accept undeclared variables
-
Hyphen / Minus
U+002D
Numeric
Represents negative value
+
Plus
U+002B
Numeric
Represents positive value
# Variable declarations
~ @r: red
~ @g: green
~ @b: blue
# Schema definitions using variables
~ $color: {string, choices: [@r, @g, @b]}
~ $schema: {
name: string,
email: email,
joiningDt: date,
color: $color
}
---
# Data using variable references
~ John Doe, '[email protected]', d'2020-01-01', @r
# Optional and nullable field declarations
~ $user: {
name: string, # Required field
email?: string, # Optional field (may be omitted)
avatar*: string, # Nullable field (may be null)
metadata*?: object # Optional and nullable field
}
# Schema with undeclared variables acceptance
~ $flexible: {
id: string,
name: string,
* # Accept additional undeclared fields
}
# Positive and negative numbers
temperature: +23.5 # Explicit positive
balance: -150.75 # Negative value
elevation: +8848 # Positive integer
debt: -5000 # Negative integer
Context Sensitive: Characters have different meanings based on position and context
Variable Prefixes: @
prefixes variable declarations and references
Schema Prefixes: $
prefixes schema definitions and references
Schema Suffixes: ?
and *
must be suffixed to field names in schema definitions
Numeric Prefixes: +
and -
prefix numeric values to indicate sign
Case Sensitive: All special characters are case-sensitive
Reserved Usage: These characters are reserved for their specific functions
Schema Definition - Detailed schema syntax and modifiers
Number Values - Numeric value formatting and signs
Structural Elements - Overview of all structural characters
Nulls in Internet Object
A Null in Internet Object represents the absence of a value or an explicitly undefined state. Null is a scalar primitive used to indicate missing, unknown, or intentionally empty data.
Null values in Internet Object support both compact and verbose representations to balance readability and space efficiency.
A null value can be expressed in two forms:
null = compactNull | verboseNull
compactNull = "N"
verboseNull = "null"
N
Uppercase N
U+004E
Compact representation of null
null
Keyword null
Multiple
Verbose representation of null
N # Compact null
null # Verbose null
Internet Object supports two equivalent representations for null values:
Compact form: N
(recommended)
Verbose form: null
N # ✅ Recommended compact form
null # ✅ Verbose form (equivalent to N)
Null explicitly represents the absence of a value, distinct from empty strings or empty arrays.
N # Null value
"" # Empty string (different from null)
[] # Empty array (different from null)
n # ❌ Lowercase not allowed
NULL # ❌ All caps not allowed
Null # ❌ Mixed case not allowed
nil # ❌ Alternative keywords not allowed
undefined # ❌ Alternative keywords not allowed
A boolean data type is used to assign boolean values to the variable i.e True and False. A boolean can be defined with the members such as type
, default
, optional
and null
. Schema of the array TypeDef should be written as,
type? : {string, choices: [bool]}
default? : bool,
optional? : {bool, F},
null? : {bool, F}
The TypeDef schema ensures the validity of bool
MemberDefs.
The first member of the bool
typedef is type
. The next snippet shows how to define a boolean type. We can pass only two values i.e true or false. It can be represented as T
, true
, F
, false
.
# Set type to bool
a: bool, b: {type: bool}
---
The next member of the bool
typedef is default
. The code snippet shows how to define a default for the bool
type. The default values are used during the processing of data/instructions if a value is not provided for a key.
# Boolean a and b with default value set to false
a?: {bool, false}, b?: {bool, default: false}
---
A member can be marked as optional. If optional
is set to true. The value of an optional
must be boolean type i.e true
or false
. Here, are some ways the the member of bool type can be marked as optional.
# Boolean a and b set to optional
a?: bool, b?: {bool, optional: true}
---
When null
is set to true, a member can accept null values. The following snippet shows how to set a member of the bool type to null.
# Set a, b so that it will accept null values
a*: bool, b*: {bool, null: true }
---
Here are some valid examples of members with bool
type...
# The members accOpen and verified are assign to bool type
accOpen: bool, Verified: {type: bool}
# The exServicemen is of bool type and default value is false
exServicemen: {bool, false}
# The regClose is set to optional and null.
regClose?*: {bool, optional: true, null: true}
Literals are predefined constant values in Internet Object that represent common data states and special values. They provide a concise way to express boolean values, null states, and special numeric values without requiring quotes or additional syntax.
Internet Object supports the following literal values:
Case Sensitive: All literals must use exact case (True
, FALSE
, NULL
are invalid)
No Quotes: Literals are written without quotes
Short Forms: Single-letter shortcuts available for brevity
- Detailed boolean type specification
- Null type and optional values
- Numeric types including special values
Booleans in Internet Object
A Boolean in Internet Object represents a logical value that can be either true or false. Boolean values are scalar primitives used to express binary states, flags, or conditional logic.
Boolean values in Internet Object support both compact and verbose representations to balance readability and space efficiency.
A boolean value can be expressed in two forms:
Internet Object supports two equivalent representations for each boolean value:
Compact form: T
for true, F
for false (recommended)
Verbose form: true
for true, false
for false
If the schema is not defined, the records in the collection can have a different structure from each other across the document. Here is the code snippet,
In the above example, the schema is not defined for the collection records so it will be parsed as,
Sending an empty record is valid only if all the variables defined in the schema are either set to null
or optional
or both.
Here in the above code snippet A
and B
is null and C
is optional thus sending an empty record is valid. Because just sending a "~"
means an empty object { }
.
In the above example, A
is null, B
is null and optional and C
is optional. So all the keys are either optional
or null
or both thus sending an empty record is valid. Because just sending a "~"
means an empty object { }
.
In the above example, the invalid record fails while parsing as the name variable is not optional
or null
. On the other hand, the age
variable is optional
as well as null
so it is valid to not pass any value for the age variable.
The Collection enables the parser to parse the rest of the document even if the previous record fails to execute.
If the record fails while parsing, that record state becomes invalid and it does not stop parsing the rest of the document.
# Record in the Collection with different structure
---
~ John, 24, {X Street, New York, NY} # valid
~ true, false # valid
~ a, b, c # valid
~ 100, 56, abc # valid
~ test, one ,457 # valid
~ XYZ, 99, female, {X Street, New York, NY} # valid
# Parsing a collection when the schema is not defined
---
~ John Doe, 20, female
~ true, false
~ marketing, 123, {Z street, Los Angeles, LA}
# Parsing records in the collection to respective indices
{
"0": "John Doe";
"1": 20;
"2": "Female";
}
{
"0": true;
"1": false;
}
{
"0": "marketing";
"1": 123;
"2": {
"0": "Z street";
"1": "Los Angeles";
"2": "LA";
}
}
# Sending Empty record in the collection
~ A*, B*: {number, default:1}, C?
---
~ James, 36, Mumbai # valid
~ Viki # valid
~ # valid
# Sending an empty record in the collection
~ $address: {street, city, state}
~ $schema: {
A*, B?*: {
number,
default: 1,
optional: true,
null: true,
max:100
},
C?: $address,
}
---
~ James, 20, {X Street, New York, NY}# valid
~ # empty but valid
~ 100 # valid
~ ABC # valid
~ # empty but valid
~ {Duck street, California, CA} # valid
# Sending empty records
~ $schema: {
name: string,
age?*: {
type: int,
default: 1,
optional: true,
null: true,
max: 25
}
}
---
~ John 25 #valid
~ William #valid
~ Ronald #valid
~ #invalid as name is not optional or null
~ George 20 #valid
# Error Handaling in Collections
~ $address: {street, city, state}
~ $schema: {
name: string,
age: {int, max:25},
$address,
}
---
# collection enables paser to parse next record even if the
# previous record fails to execute
~ James, 20, {X Street, New York, NY} # valid
~ Alex, 30, {Z Street, Los Angeles, California} # invalid
~ Bob, 20, {Melrose Street, San Fransisco, California} # valid
true
Boolean
True value
Yes
T
Boolean
True value (short form)
Yes
false
Boolean
False value
Yes
F
Boolean
False value (short form)
Yes
null
Null
Null/empty value
Yes
N
Null
Null/empty value (short form)
Yes
Inf
Number
Positive infinity
Yes
-Inf
Number
Negative infinity
Yes
NaN
Number
Not a Number
Yes
# Boolean literals
~ isActive: true, verified: F, isDeleted: false, visible: T
# Null literals
~ middleName: null, nickname: N
# Special numeric literals
~ maxValue: Inf, minValue: -Inf, result: NaN
boolean = compactBoolean | verboseBoolean
compactBoolean = "T" | "F"
verboseBoolean = "true" | "false"
T
Uppercase T
U+0054
Compact representation of true
F
Uppercase F
U+0046
Compact representation of false
true
Keyword true
Multiple
Verbose representation of true
false
Keyword false
Multiple
Verbose representation of false
T # Compact true
F # Compact false
true # Verbose true
false # Verbose false
T # ✅ Recommended compact form
true # ✅ Verbose form (equivalent to T)
F # ✅ Recommended compact form
false # ✅ Verbose form (equivalent to F)
t # ❌ Lowercase not allowed
f # ❌ Lowercase not allowed
TRUE # ❌ All caps not allowed
FALSE # ❌ All caps not allowed
True # ❌ Mixed case not allowed
False # ❌ Mixed case not allowed
1 # ❌ Numeric representation not allowed
0 # ❌ Numeric representation not allowed
Raw strings in Internet Object
A Raw String in Internet Object is a sequence of Unicode codepoints prefixed with r
or R
and enclosed in either single quotes (' U+0027
) or double quotes (" U+0022
). Raw strings are ideal for text containing many backslashes, quotes, or structural characters, such as file paths or regular expressions. They do not support escape sequences except for the enclosing quote, which can be represented by doubling the enclosing quote character inside the string.
Raw strings are scalar values. They preserve all content as written, including whitespace, newlines, and Unicode characters.
A raw string is prefixed with r
or R
and enclosed in either single or double quotes. The only special rule is that the enclosing quote character inside the string must be represented as two consecutive enclosing quotes.
rawString = "r" (singleQuotedRaw | doubleQuotedRaw)
singleQuotedRaw = "'" { character | doubleSingleQuote } "'"
doubleQuotedRaw = '"' { character | doubleDoubleQuote } '"'
character = any Unicode codepoint except the enclosing quote
doubleSingleQuote = "''" (represents a single quote inside a single-quoted raw string)
doubleDoubleQuote = '""' (represents a double quote inside a double-quoted raw string)
The following characters are used to structure raw strings:
r
Raw Prefix
U+0072
Indicates raw string type
'
Single Quote
U+0027
Encloses string, doubled inside for escape
"
Double Quote
U+0022
Encloses string, doubled inside for escape
(space, tab, etc.)
Whitespace
Multiple
Preserved as written
Any
Any Unicode codepoint
Multiple
Allowed, except unescaped enclosing quote
Note: The reverse solidus (
\\
U+005C) is always treated as a literal character in raw strings—there is no escaping with backslash.
Examples of valid raw strings:
r'C:\program files\example\app.exe'
r"C:\program files\example\app.exe"
r'^(19|20)\d\d([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$'
r"^(19|20)\d\d([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$"
r'जॉन डो'
r"Can contain Ucharacters 😃"
r'A Unicode string (😃) which does not force you to escape\ncharacters like \, \n or anything except a single quote char ''''.'
r"A Unicode string (😃) which does not force you to escape\ncharacters like \, \n or anything except a double quote char \"\"."
r'Jonas D''costa' # Contains a single quote inside
r"He said, ""Hello!""" # Contains a double quote inside
Whitespace: Leading, trailing, and internal whitespace are preserved.
No Escaping: No escape sequences are supported except for doubling the enclosing quote to represent it inside the string.
Multiline: Newline and carriage return characters are preserved.
Comments are not allowed within raw strings, but may appear outside or between values as per Internet Object comment rules.
Examples of invalid raw strings:
rC:\program files\example\app.exe # ✗ Missing quotes (should be r'...') or r"..."
r'Jonas D'costa' # ✗ Unescaped single quote inside (should be r'Jonas D''costa')
r"He said, "Hello!"" # ✗ Unescaped double quote inside (should be r"He said, ""Hello!"")
r'Unclosed string # ✗ Missing closing quote
r'Contains \\ escapes' # ✗ Backslash is not an escape, just literal
Internet Object preserves:
All Unicode codepoints and whitespace as written
The use of doubled enclosing quotes for embedded quotes
It does not interpret or enforce:
Application-specific constraints
Escaping beyond doubled enclosing quotes
Internet Object is a data interchange format designed for modern network communication. This specification introduces Internet Object as a text-based, schema-first, document-oriented, and streamable format that prioritizes human readability and language independence. Internet Object aims to optimize the serialization of structured data for efficient transmission between servers and clients across the internet.
Regular strings in Internet Object
A Regular String in Internet Object is a sequence of Unicode codepoints enclosed in single quotes (' U+0027
) or double quotes (" U+0022
). Regular strings allow any character, including whitespace and structural characters, and support escaping for special codepoints. This makes them suitable for text that requires leading/trailing whitespace, structural characters, or complex escaping.
Regular strings are scalar values. They preserve all content as written, including whitespace and Unicode characters.
A regular string is enclosed in single or double quotes and may contain any Unicode codepoint, with support for escape sequences.
Examples of valid regular strings:
Whitespace: Leading, trailing, and internal whitespace are preserved.
Escaping: Only designated escape sequences are interpreted: \n
, \"
, \\
, \'
, \b
, \f
, \r
, \t
, \u
(with exactly 4 hex digits and must be a valid Unicode codepoint), and \x
(with exactly 2 hex digits). All others (e.g., \o
) are left as a literal backslash and character. For example, "hell\\o"
emits hello
.
Multiline: Newline and carriage return characters are preserved.
String Comparison: Escaped and unescaped forms are equivalent if they represent the same Unicode codepoints.
Comments are not allowed within regular strings, but may appear outside or between values as per Internet Object comment rules.
Examples of invalid regular strings:
Internet Object preserves:
All Unicode codepoints and whitespace as written
Escaped and unescaped forms (syntactic fidelity)
It does not interpret or enforce:
Application-specific constraints
Normalization of escape sequences (beyond equivalence)
Numbers in Internet Object
Numbers in Internet Object provide accurate numerical representation for various applications, from simple counting to complex financial calculations. Internet Object supports three distinct numeric data types—Number, BigInt, and Decimal—each designed to meet different numerical requirements in modern applications.
(64-bit floating-point): Standard IEEE 754 double-precision numbers, ideal for general-purpose calculations and fractional values.
: Arbitrary-precision integers for extremely large whole numbers that exceed 64-bit limitations.
: Fixed-precision decimal values with exact arithmetic, essential for financial calculations and applications requiring precise decimal representation.
Internet Object supports various number formats. The table below distinguishes between decimal integers and regular (floating-point) numbers, and provides recommendations:
Note: Bases other than decimal (base 10)—that is, binary (base 2), octal (base 8), and hexadecimal (base 16)—can only represent integers, not fractional or decimal values. For non-integer values, use decimal (base 10) or scientific notation.
Each number type uses a distinct suffix for identification:
See for details on undefined and infinite results (supported only by Number).
Note: Alternative base formats (binary, octal, hexadecimal) are documented within each number type specification.
Note: The term "decimal" is used in two contexts:
Decimal (base-10): The common numeral system used by all number types
Decimal (data type): A specific fixed-precision type for exact arithmetic
- Overview of all Internet Object value types
- Number validation and constraints
regularString = '"' { dqChar | escapeSequenceDQ } '"' | '\'' { sqChar | escapeSequenceSQ } '\''
dqChar = any Unicode codepoint except '"' or '\\'
sqChar = any Unicode codepoint except '\'' or '\\'
escapeSequenceDQ = '\\' ( '"' | '\'' | '\\' | 'b' | 'f' | 'r' | 'n' | 't' | unicodeEscape | hexEscape | other )
escapeSequenceSQ = '\\' ( '\'' | '"' | '\\' | 'b' | 'f' | 'r' | 'n' | 't' | unicodeEscape | hexEscape | other )
unicodeEscape = 'u' hex4
hexEscape = 'x' hex2
hex4 = 4 hexadecimal digits (must form a valid Unicode codepoint)
hex2 = 2 hexadecimal digits
other = any character except 'u' or 'x'
"
Double Quote
U+0022
Encloses the string, must be escaped inside
'
Single Quote
U+0027
Encloses the string, must be escaped inside
\\
Reverse Solidus
U+005C
Escape character
(space, tab, etc.)
Whitespace
Multiple
Preserved as written
Any
Any Unicode codepoint
Multiple
Allowed, except unescaped enclosing quote
"John Doe"
'John Doe'
" John Doe "
' John Doe '
"Peter D'mello"
'Peter D\'mello' # Escaped single quote inside single-quoted string
"जॉन डो"
'Can contain unicode characters 😃'
"Lorem ipsum dolor sit amet consetetur sadipscing\nelitr sed diam nonumy eirmod.\n\nTempor invidunt ut labore et dolore magna aliquyam\nerat sed diam voluptua"
'Lorem ipsum dolor sit amet consetetur sadipscing\nelitr sed diam nonumy eirmod.\n\nTempor invidunt ut labore et dolore magna aliquyam\nerat sed diam voluptua'
"She said, \"I Love it\""
'She said, "I Love it"'
"\x3A" # Escaped with two-digit hex
'\x3A'
"\u00AF" # Escaped with four-digit hex
'\u00AF'
"\uD83D\uDE00" # UTF-16 surrogate pair for emoji
'\uD83D\uDE00'
John Doe # ✗ Not quoted (should be "John Doe" or 'John Doe')
"John Doe # ✗ Missing closing quote
'John Doe # ✗ Missing closing quote
"John Doe"" # ✗ Extra quote at end
'John Doe'' # ✗ Extra quote at end
"She said, "I Love it"" # ✗ Unescaped internal quote (should be \"I Love it\")
'She said, 'I Love it'' # ✗ Unescaped internal quote (should be \'I Love it\')
"\q" # ✗ Invalid escape sequence
'\q' # ✗ Invalid escape sequence
Decimal integer (base 10)
Number, BigInt
BigInt: large integers, Number: general-purpose integers
Decimal (floating-point)
Number, Decimal
Decimal: financial/precise decimals, Number: general-purpose decimals
Binary (base 2)
Number, BigInt
BigInt: large binary integers, Number: general binary values
Octal (base 8)
Number, BigInt
BigInt: large octal integers, Number: general octal values
Hexadecimal (base 16)
Number, BigInt
BigInt: large hex integers, Number: general hex values
Scientific notation
Number, Decimal
Decimal: precise scientific/financial, Number: general scientific
Special values
Number only
NaN and Infinity for undefined/infinite results
42 # Number (standard floating-point)
42n # BigInt (arbitrary-precision integer)
42.50m # Decimal (fixed-precision decimal)
General calculations
Number
Standard performance and compatibility
Financial amounts
Decimal
Exact precision, no rounding errors
Large counters/IDs
BigInt
No precision limits for integers
Scientific notation
Number
Built-in floating-point support
Cryptographic values
BigInt
Handles arbitrarily large integers
Unbounded integer values for handling extremely large numbers
A BigInt in Internet Object represents arbitrary-precision integers that can handle numeric values exceeding the limitations of standard 64-bit number representations. BigInt is a scalar primitive used for extremely large whole numbers with perfect precision, such as in cryptographic operations, large-scale counting, or mathematical computations requiring unbounded integer arithmetic.
Unlike the regular Number type, which is limited to safe integers within approximately ±9 quadrillion (±2^53-1), BigInt can represent integers of arbitrary length, ensuring that large numerical operations remain exact regardless of magnitude.
A BigInt value is expressed as an integer with the n
suffix:
bigint = ["-" | "+"] (decimalBigInt | binaryBigInt | octalBigInt | hexBigInt)
decimalBigInt = digit+ "n"
binaryBigInt = "0b" binaryDigit+ "n"
octalBigInt = "0o" octalDigit+ "n"
hexBigInt = "0x" hexDigit+ "n"
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
binaryDigit = "0" | "1"
octalDigit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7"
hexDigit = digit | "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f"
n
BigInt Suffix
U+006E
Identifies value as BigInt
0-9
Digits
Multiple
Standard decimal digits
-
Minus Sign
U+002D
Indicates negative numbers
0b
Binary Prefix
Multiple
Binary number indicator
0o
Octal Prefix
Multiple
Octal number indicator
0x
Hex Prefix
Multiple
Hexadecimal number indicator
123n # Positive BigInt
-42n # Negative BigInt
0n # Zero as BigInt
9007199254740992n # Beyond Number.MAX_SAFE_INTEGER
0b1010n # Binary (10 in decimal)
0o7777n # Octal (4095 in decimal)
0xFFn # Hexadecimal (255 in decimal)
0xFFFFFFFFFFFFFn # Large hex BigInt
BigInt values support multiple equivalent representations:
42n # ✅ Standard decimal BigInt
0x2An # ✅ Hexadecimal BigInt (equivalent to 42n)
0b101010n # ✅ Binary BigInt (equivalent to 42n)
0o52n # ✅ Octal BigInt (equivalent to 42n)
BigInt values represent whole numbers only and do not support fractional components:
5n + 3n # 8n (addition)
5n * 3n # 15n (multiplication)
5n / 3n # 1n (integer division, truncates toward zero)
5n % 3n # 2n (remainder)
BigInt values maintain exact precision regardless of magnitude:
9007199254740991n + 1n # 9007199254740992n (exact)
9007199254740991n + 2n # 9007199254740993n (exact)
123 # ❌ Missing 'n' suffix (should be 123n)
123.45n # ❌ BigInt cannot have decimal point (use Decimal for fractions)
123nn # ❌ Multiple suffixes not allowed (should be 123n)
n123 # ❌ Suffix must be at the end (should be 123n)
0b # ❌ Missing binary digits (should be 0b1n)
0xn # ❌ Missing hex digits (should be 0x1n)
Internet Object preserves:
The chosen representation form (decimal, binary, octal, hex)
Exact integer precision regardless of magnitude
Syntactic fidelity (as written, except that an explicit plus sign is not preserved)
However, it does not interpret:
Mathematical relationships between values
Domain-specific constraints on large integers
Performance implications of arbitrary-precision arithmetic
Such semantics are the responsibility of the schema layer, validators, or application logic.
Number Types Overview - Launcher for all number types and formats
Number - For standard floating-point numbers
Decimal - For fixed-precision decimal arithmetic
The header section of the internet object document can have single or multiple schema definitions
~ $address: {
street: string,
zip:{string, maxLength:5},
city: string
}
~ $person: {
name:string,
age:int,
homeAddress?:$address,
officeAddress?:$address
}
~ $schema: $person
---
Spiderman, 25, {Queens, 50010, New York}, {Bond Street, 50001, New York}
In the above example, the schema definitions are created for reuse to improve the readability of a schema. The schema definition created for address is reused in the person
schema definition.
ISC (Internet Systems Consortium) License
Copyright 2020 Mohamed Aamir Maniar.
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
This poem encapsulates the core guiding principles that shape the design and objectives of the Internet Object format.
The poem serves as a unique and memorable medium to communicate the foundational principles that form the basis of the Internet Object format. By creatively capturing these concepts in verse, the poem enables readers to appreciate and remember the essence of the data interchange system more effectively. The Internet Object format is designed to be efficient, clear, and versatile in facilitating data interchange, and the poem highlights these attributes by artistically expressing the philosophy and goals that drive its development. The poem, therefore, not only adds an engaging element to the specification but also reinforces the core values of the Internet Object format.
Size holds weight, in bytes confined, Small prevails, large left behind.
Simplicity shines over complexity's shroud, Readability echoes, accurate and loud.
Reusability births productivity's rise, Verbosity's burden efficiency defies.
Data, definitions, separate ways, Together they clutter, apart they amaze.
Headers and data, distinctions drawn, Confusion dissolves, clarity's dawn.
Errors and statuses, data's divide, Their entanglement brings chaos inside.
Two lone records, states unswayed, No interference, connections unmade.
Trust not the sender, vigilance displayed, Expect the unanticipated, foundations laid.
Surprises, enchanting, yet beware, Not all of them good, handle with care.
The internet object schema defines six data types that include string, number, int, int32, int16, byte, email, url, datetime, date, time, bool, object, array or any.
Typedefs are a memberdef schema for the specified type. They define the constraints for the particular data type. The following example
type: { string, choices: [
string, email, url, datetime, date, time,
number, int, int32, int16, byte,
object, array, bool
]
}
type : {string, choices: [string, email, url, datetime, date, time]},
default? : string,
choices? : [string],
pattern? : string,
maxLen? : {int, min:0},
len? : {int, min:0},
optional? : {bool, F},
null? : {bool, F}
Some of the valid String MemberDef values are...
# The name is string and default value is ""
name: {string, ""}
# The website is of url type!
website: {url, optional:T}
# The rgb's default is red, and choices are red, green, blue
rgb: {string, red, [red, green, blue]}
# The description is string that can have maximum length of 500 characters
description: {string, maxLen:500} #
As shown in the example above, Objects, Numbers, Arrays, Boolean, and Any have their respective TypeDef.
Strings in Internet Object
Strings in Internet Object represent sequences of Unicode codepoints. They are used for textual data and always preserve whitespace and formatting within their boundaries.
Internet Object supports three distinct string types, each with unique syntax and use cases:
stringValue = openString | regularString | rawString
Unquoted, simplest form, ends at structural character or whitespace.
John Doe
Quoted with double quotes, supports escaping and structural characters.
"John Doe"
Prefixed with r
, quoted with single or double quotes, minimal escaping.
r'C:\path'
or r"C:\path"
All string types preserve whitespace and Unicode content as written.
Open String: For simple, unstructured text without leading/trailing whitespace or special characters.
Regular String: When you need to include structural characters, whitespace, or require escaping.
Raw String: For text with many backslashes or quotes (e.g., file paths, regex), with minimal escaping and r
prefix.
An object is the fundamental unit of Internet Object document, it can be defined with the members such as schema
, type
, default
, optional
and null
.
The TypeDef schema ensures the validity of object
MemberDefs.
In the internet object document, the object may or may not be defined with the member called schema
. But it is always recommended to define the schema for an object.
If the schema is not defined then the user can pass an object with values of any
type i.e anyOf: [string, object]
.
The above code snippet represents how the object can be defined with the typedef member schema
.
The second member of the typedef is type
. By default, the object can be of string or an object type. Here the next snippet shows how the object type can be defined.
The next member in the object
typedef is default
. Here is how the default values can be defined for an object.
The Object when set to null
will accept null values. Here the code snippet demonstrates the way how an object can accept a null value.
A member of an object type can be set to optional. Here are some of the ways through which a member of an object type can be made optional.
An empty object is useful for accepting any object value irrespective of its structure. The empty object definitions can be created using empty curly braces syntax or ignoring schema. Here are some ways in which empty object definitions can be created.
A simple object is an ordered collection of key-value pair that avoids nesting of the object and may or may not contain a child object as shown in the code snippet.
An object can be defined with the MemberDef as shown in the snippet below.
An Object can be nested inside another object. Accessing a nested object is similar to accessing a nested array. Here is the code snippet that shows how objects can be nested.
Defining dynamic schema allows users to add a dynamic object as shown in the snippet below.
The object can be represented as as shown here.
Time can be represented as, HH:mm:ss.SSS
or HHmmss.SSS
i.e it can be passed with or without separators (: U+003A)
.
It uses a 24-hour clock system. Midnight is a special case and it may be referred to as "00:00"
or "24:00"
. However, ISO 8601-1: 2019 no longer permits "24:00"
.
The code snippet demonstrates how to define and use time
In the Internet Object Document.
The Time is derived from the String type, hence it shares the same as the String. However, Time enforces additional constraints with the respective time format and the same is applicable to the Time MemberDef.
The header of an Internet Object document is positioned at the beginning of the document and serves a crucial role in defining the schema or associated definitions for the data it contains. This section includes essential metadata, context, variables, and schema references for the document's content. It plays an important role in ensuring that the data is presented in a consistent format and provides the necessary information for accurate interpretation and processing.
[ Header Image Placeholder ]
The schema is a fundamental component of the Internet Object format, defining the structure and semantics of the data within an Internet Object document. When the header contains only a schema, it is referred to as a "default schema." This schema is typically used to outline the structure of the data included in the document, separating the structure definition from the data itself. This separation makes the data more compact, readable, and easier to process. For more detailed information about schemas, refer to .
In this schema example, five keys are defined with additional details:
name
: Represents a standard key, expected to contain a value such as a string.
age:int
: Specifies that the age
key should contain an integer value, indicating the data type explicitly.
address
: Another standard key, which could hold a more complex value like a string or an object, depending on the context.
isActive?
: The question mark (?
) signifies that the isActive
key is optional, meaning it may or may not be present in the data.
remark
: Represents a standard key, expected to contain a value, likely a string, which could hold additional comments or notes.
This schema not only defines the structure but also includes type annotations and optionality, enhancing the clarity and robustness of the data model. By using this schema, the document can ensure consistent and accurate data representation, making it easier to process and interpret across different systems.
See this page for more information about .
Definitions, at their core, are collections of key-value pairs used to declare metadata, variables, complex schemas, and other key-value pairs within the header of an Internet Object document.
In this example, the header contains response metadata and schema details presented as Definitions, rather than using a Default Schema as seen in the previous example. The Definitions provide metadata that specify the page size (pageSize
), the current page number (currentPage
), and the total record count (recordCount
). Additionally, more complex structures are defined, such as an address schema ($address
) with nested keys (street
, city
, state
) and a higher-level schema ($schema
) that references both simple and complex data types. The $schema
is a reserved key used to define the default schema for the document.
For further information about , click the link.
For frequently passing object data between the system over the internet there is a need to stream objects over a single connection.
As the collection enables embedding more than one independent record in the document because of its nature it allows streaming real-time data changes. So that the application can react immediately to the changing events in real-time.
Multiple records can be sent in batches after validating with the schema as,
After you have received the first batch of records, the collection allows you to receive more records for the same collection separately. The Internet Object processor should take care of merging the stream of data into the same collection.
Contributor
Contribution
Ujwala Mhashakhetri
Document Drafting
Kabir Maniar
Document Drafting and Diagrams
schema? : {any, anyof: [string, object]},
default? : {},
type? : {string, choices: [object]},
optional? : {bool, default: F},
null? : {bool, default: F}
# An object with schema
a: {{city, state, zip}, ...}
# Assigning schema through memberdef
b: {default: N, schema: {city, state, zip}, null: T}
# Set type to object
a: object, b: {type: object}
---
# Set default value to null for a and b
a?: {object, N}, b?: {object, default: N}
---
# Set an empty object to null.
a*: {}
#Assign null value to empty object by setting null: T.
b: {{}, null: T}
# Set default value of an empty object to null.
c?*: {{}, default: N}
# Set default value of object {x, y, z} to null.
d?*: {{x, y, z}, N}
---
# Set an empty object to optional
a?: {}
b?: object
# Set optional: T for empty object
b: {{}, optional: T}
# Assign optional value to empty object
c: {{}, default: N, null: T, default: T}
# Set obect {x, y, z} to optional and null
d*?: {{x, y, z}, N}
---
# Defining an empty object
address: {}
#or
address: object
#or
address: {schema:{}}
---
# A simple object as a schema
name, age, address, tags
---
# A simple object with child object
address: { street: string, city: string, state: string }
---
# Defining meberdef for an object
address: {
schema: {
street: string,
city: string,
state: string,
location*: {
{ lng: number, lat: number }
default: N,
null: T
}
},
default: N,
null: T
}
---
# Nested object
name: {string, maxLen: 20},
office: {
address: {
street: string,
city: string,
state: string,
location*: {
{ lng: number, lat: number }
default: N,
null: T
}
},
contact: {
mobile: number,
fax: number,
emails: {
primary: email,
secondary: email
}
}
}
# Defining dynamic schema for an object
address: {
any,
anyOf: [
{city: string, state: {string: len: 2}},
{street: string,
city: string,
state: {string: len: 2}, zip?: string}
]
}
# The schema directly assigned to the address
address: {street, city, state}
# The schema assinged through the memberDef. This approach
# allows designer to set additional options such as default.
address?: {{street, city, state}, default: N}
name, age:int, address, isActive?, remark
---
~ pageSize: 1
~ currentPage: 1
~ recordCount: 4
~ $address: {street, city, state}
~ $schema: {name, age, $address}
---
Standard 64-bit floating-point numbers in Internet Object
A Number in Internet Object represents a 64-bit double-precision floating-point value conforming to the IEEE 754 standard. Numbers are scalar primitives used to express integers, fractional values, and special numeric constants.
Numbers in Internet Object support various representations including different bases (binary, octal, hexadecimal), scientific notation, and special values like NaN and Infinity.
A number can be expressed in multiple forms:
number = ["-" | "+"] (
decimalNumber
| binaryNumber
| octalNumber
| hexNumber
| scientificNumber
) | specialValue
decimalNumber = digit+ ["." digit+]
binaryNumber = "0b" binaryDigit+
octalNumber = "0o" octalDigit+
hexNumber = "0x" hexDigit+
scientificNumber = (digit+ ["." digit+] | "." digit+) ("e" | "E") ["-" | "+"] digit+
specialValue = "NaN" | "Inf" | "-Inf" | "+Inf"
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
binaryDigit = "0" | "1"
octalDigit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7"
hexDigit = digit | "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f"
0-9
Digits
Multiple
Standard decimal digits
.
Decimal Point
U+002E
Separates integer and fraction
-
Minus Sign
U+002D
Indicates negative numbers
+
Plus Sign
U+002B
Optional positive indicator
e
/E
Exponent
Multiple
Scientific notation exponent
0b
Binary Prefix
Multiple
Binary number indicator
0o
Octal Prefix
Multiple
Octal number indicator
0x
Hex Prefix
Multiple
Hexadecimal number indicator
Numbers in decimal format can include integers and fractional values, with optional sign prefixes:
# Simple integers
42 # Integer
-17 # Negative integer
+17 # Positive integer (explicit)
# Fractional numbers
3.14159 # Fractional number
-0.5 # Negative fractional
+0.5 # Positive fractional (explicit)
# Zero
0 # Zero
+0 # Positive zero (explicit)
-0 # Negative zero (explicit)
A decimal number consists of one or more digits, optionally preceded by a sign (+ or -), and optionally including a decimal point followed by one or more digits.
Numbers can be expressed in binary, octal, or hexadecimal notation:
Binary representation uses 0b
or 0B
prefix followed by binary digits (0-1):
0b1010 # Binary 1010 (10 in decimal)
0B1111 # Binary 1111 (15 in decimal)
0b0 # Binary 0
-0b1010 # Negative binary (-10 in decimal)
+0B1100 # Positive binary (12 in decimal)
Octal representation uses 0o
or 0O
prefix followed by octal digits (0-7):
0o755 # Octal 755 (493 in decimal)
0O644 # Octal 644 (420 in decimal)
0o0 # Octal 0
-0o755 # Negative octal (-493 in decimal)
+0O377 # Positive octal (255 in decimal)
Hexadecimal representation uses 0x
or 0X
prefix followed by hex digits (0-9, A-F):
0xFF # Hexadecimal FF (255 in decimal)
0x10 # Hexadecimal 10 (16 in decimal)
0XDeadBeef # Mixed case hex (3735928559 in decimal)
-0xFF # Negative hex (-255 in decimal)
+0x10 # Positive hex (16 in decimal)
Prefixes: Both lowercase (0b
, 0o
, 0x
) and uppercase (0B
, 0O
, 0X
) are supported
Hex digits: Both uppercase (A-F
) and lowercase (a-f
) are valid
0xFF # ✅ Lowercase prefix, uppercase digits
0XFF # ✅ Uppercase prefix, uppercase digits
0xff # ✅ Lowercase prefix, lowercase digits
0Xff # ✅ Mixed case (all equivalent)
Scientific notation expresses numbers using exponential form with e
or E
:
1.23e4 # 1.23 × 10⁴ = 12300
1.23E4 # Same as above (case insensitive)
1.23e-4 # 1.23 × 10⁻⁴ = 0.000123
-2.5e+3 # -2.5 × 10³ = -2500
5e3 # 5 × 10³ = 5000
.5e2 # 0.5 × 10² = 50
6.022e23 # Avogadro's number
1e-10 # Very small number
-3.14159e0 # -3.14159 × 10⁰ = -3.14159
Mantissa: The significant digits (before e
/E
)
Exponent marker: e
or E
(case insensitive)
Exponent: The power of 10 (can be positive, negative, or zero)
# Format: [sign]mantissa[e|E][sign]exponent
1.5e+10 # Explicit positive exponent
1.5e-10 # Negative exponent
1.5e10 # Implicit positive exponent
Numbers support multiple equivalent representations:
42 # ✅ Standard decimal
0x2A # ✅ Hexadecimal (equivalent to 42)
0b101010 # ✅ Binary (equivalent to 42)
0o52 # ✅ Octal (equivalent to 42)
4.2e1 # ✅ Scientific notation (equivalent to 42)
.5 # ❌ Must have leading digit
5. # ❌ Must have trailing digit if decimal point used
0b # ❌ Missing binary digits
0b12 # ❌ Invalid binary digit '2'
0o89 # ❌ Invalid octal digits '8' and '9'
0x # ❌ Missing hex digits
0xGH # ❌ Invalid hex digits 'G' and 'H'
1.2.3 # ❌ Multiple decimal points
0b 1010 # ❌ Space between prefix and digits
0o 755 # ❌ Space between prefix and digits
0x FF # ❌ Space between prefix and digits
1e # ❌ Missing exponent in scientific notation
1e+ # ❌ Missing exponent digits
1.23ee4 # ❌ Multiple exponent markers
1.2.3e4 # ❌ Multiple decimal points in mantissa
Internet Object preserves:
The chosen representation form (decimal, binary, octal, hex, scientific)
Whitespace (non-significant in interpretation)
Syntactic fidelity (as written, except that an explicit plus sign is not preserved)
However, it does not interpret:
Mathematical relationships between values
Precision requirements beyond IEEE 754
Domain-specific numeric constraints
Such semantics are the responsibility of the schema layer, validators, or application logic.
Number Types Overview - Launcher for all number types and formats
BigInt - For arbitrary-precision integers
Decimal - For fixed-precision decimal arithmetic
Special Numeric Values - NaN and Infinity
The Internet Object format is a document-oriented format that emphasizes the separation of header and data. This structure is similar to that of HTML, and MIME, where the header is kept separate from the data or body.
In an Internet Object document, the header is optional but can be used to define schemas and definitions. The data section always starts with the ---
separator. This separator is the first element of the data section and is mandatory to distinguish it from the header.
[ Internet Object Document Structure Diagram ]
If an Internet Object document includes both a header and a data section you can call it a full document.
# Header
name, age:int, address: {street, city, state}, active # Header
# Data Section
---
John Doe, 25, {Bond Street, New York, NY}, T
When an Internet Object document contains only a data section, it is okay to omit the ---
separator. Such documents are sent to the server without any header because the schema is either not required or already known to the recipient.
With Separator:
---
John Doe, 25, {Bond Street, New York, NY}, T # Data section
Without Separator:
~ John Doe, 25, {Bond Street, New York, NY}, T
~ Jane Done, 48, {Malibu Point 10880, Malibu, CA}
In many cases, a query-generating document may not yield any results. In such cases, you can use the header with result metadata to send the query and the results. However, it is important to include the ---
separator to mark the end of the header and the start of the data section.
# Header Record Metadata
~ reocordCount: 0
~ pageSize: 10
~ currentPage: 1
~ nexPage: N
~ prevPage: N
# Empty Data Section
---
Internet Object document can contain multiple data sections. This facility allows user to provide multiple types of data collection to be embedded in the single document.
# Schema section
~ $address: {street, city, state, zip} # Adddress Schema
~ $person: {firstName, lastName, age, gender }
# The collection of person
--- $person
~ John, Doe, 25, M
~ Jane, Doe, 22, F
# The address
--- $address
~ Bond Street, New York, NY, 500001
~ Georeg Street, New York, NY, 500002
Internet Object document structure is designed to be simple and flexible. The next section will discuss the Header and Data section in detail.
The Internet Object format includes several structural characters, literals, and other special characters that are used to structure and delimit data within a document. These characters are used in conjunction with objects, strings, arrays, numbers, and whitespace to create complex and flexible data structures.
Structural Characters - Core syntax characters that define data organization
Literals - Predefined constant values (booleans, null, special numbers)
Other Special Characters - Functional modifiers for variables, schemas, and values
Whitespaces - Comprehensive Unicode whitespace character support
Frequently Asked Questions about Internet Object (In no particular order). These are the questions that have been frequently asked after the concept was previewed to the community.
As the Greek philosopher, Heraclitus, said: “change is the only constant.”. Internet Object was created to address some of the issues found in JSON which happens to be the most prominent data serialization format today. For more information, please read the story.
One of the primary objectives of the Internet Object is to be solely a text-based human-readable serialization format. Hence, the current version of Intenet Object natively does not support direct binary data. Binary data may be escaped using the algorithms like Base64 so that it can be passed as a string value.
JSON support was not one of the objectives of creating the Internet Object. However, the final format turned out to be JSON compatible. So yes, Internet Object understands the JSON format.
Yes, Internet Object schema can validate an Internet Object document as well as a JSON object.
The uncompressed (non-gzipped) IO document is generally 40% smaller. When compared with gzipped versions of JSON and IO documents, we saw unpredicatable results. Sometimes IO document was smaller than JSON, sometimes it was around the same size. On a few occasions, the JSON document was a bit smaller than the IO version.
Internet Object is a very simple format. It is very easy to build the document just by concatenating the strings! In such cases, it is very fast to build the document. However, in reality, the performance of the parsing depends upon the parser and other factors. A well-written parser will be faster than poorly written parsers.
Great, that you would like to support Internet Object. You can contribute in many ways.
Some of them are...
Join the team that is developing an Internet Object library in your favorite language.
Write a blog or article about the Internet Object
Help friends and colleagues get started with the concept
Help us develop various technical documentations
Be a proofreader and help us correct the specification and document language
Translate the documentation in various languages
Spread the word about Internet Object
Value
Description
Example
HH
24-hour clock hour, (00-23
)
01
mm
Minutes, Decimal number (00-59
)
46
ss
Seconds, Decimal number (00-59
)
55
SSS
Milliseconds, three-digit decimal number (000-999
)
500
Time with separators:
Time without Separators:
HH:mm:ss.SSS
= 05:24:34.555
HHmmss.SSS
= 052434.555
HH:mm:ss
= 05:24:34
HHmmss
= 052434
HH:mm
= 05:24
HHmm
= 0524
HH
= 05
HH
= 05
# Set transactionTime with derived type as time
transactionTime: time
---
~ 05:24:34:555
~ 05:24:34 # parsed as 05:24:34:000
~ 05:24 # parsed as 05:24:00:000
~ 05 # parsed as 05:00:00:000
Internet object specifies the following number derived types and also provides built-in support for them.
The following snippet represents a number and its derived types.
# Number and its derived types
{ applicationNo: int,
rollNo: int32,
totalScore: int16,
percentage: number,
paperCode: byte
}
---
{
8754489612,
125447,
566,
94.33,
48
}
Here the applicationNo
is of integer type and will only accept integers. Similarly, rollNo
, totalScore
, percentage
and paperCode
are of different types such as int32
, int16
, number
, and byte
. Therefore they will only accept values with the defined types for the respective variable.
An Internet Object array can be defined with the members such as type
, default
, len
, minLen
, maxLen
, optional
and null
. Schema of the array TypeDef should be written as,
The TypeDef schema ensures the validity of array
MemberDefs.
The first member of the internet object array is a schema. When the schema is defined all array items must be validated against the schema. The code snippet demonstrates how the array can be defined with the schema.
The next member in the array
typedef is default
. Here is how the default values can be defined for an array.
The value of minLen
must be a non-negative integer. The array instance is valid only if, number of items in the array will be greater than or equal to the value of minLen
. The code snippet shows how to define minLen
for an array.
The value of maxlen
must be a non-negative integer. The array instance is valid only if, number of items in the array will be less than or equal to the value of the maxlen
. Here the code snippet shows how to define maxLen
for an array.
The next member in the array
typedef is length represented as len
, it must be a non-negative integer. The Array instance is valid only if, the number of items in the array will be exactly equal to the value of len
. Here is how the len
can be defined for an array.
An array when set to null
will accept null values. Here the code snippet demonstrates the way how an array can accept a null value.
A member of an array type can be set to optional. Here a code snippet demonstrates different ways how an array can be set to optional
An array type can be specified as shown in the snippet below.
Some of the valid examples of members with array type are...
The above example can be simplified as,
An array can have mixed values as shown in the snippet below.
An array containing another array represents a nested array as shown in the code snippet.
A multidimensional array is an array with more than one dimension. Two and three-dimensional arrays are called multidimensional arrays. Here is the code snippet that demonstrates how a multidimensional array is represented.
Similar to Email, an URL can also be passed as a string. The URL format is derived from the recommended by W3C.
URL format follows the syntax specified in the
The code snippet shows how to define an url
In the Internet Object Document.
The Email is derived from the String type, hence it shares the same as the String. However, URL enforces additional constraints with the respective url format.
The choices
can be added to member variables in the url
so that it is restricted to the fixed set of available choices. Choices must be an array of valid url
. The code snippet here shows how to add choices for the url.
User may specify pattern
for the url
by defining pattern
as,
When a variable is classified as an int16
in the schema then it will be classified as an integer with a size of 16 bits or 2 bytes. The range of values is from -32768
to +32767
.
The int16
is derived from the number type that shares the sameas the Number i.e type
, default
, choices
, max
, min
, multipleOf
, divisibleBy
, optional
and null
while enforcing the additional constraint that the number must be of int16
type.
By default the max
value of byte
type variable is +32767
and and min
is -32767
.
schema? : {[$type, $memberdef, [any]], default:[any]}
default? : array,
minLen? : {int, minLen: 0},
maxLen? : {int, minLen},
len? : {int, minLen: 0},
null? : {bool, F}
optional? : {bool, F}
type? : {string, choices:[array]}
---
# An array that can hold any values
a: [],
# An array of number
a: [number],
# An array of address object
c: [{street, city, state}],
# A fixed sized array (len 5) of string that can accept maxLen of 10 characters
d: {[{string, maxLen:10}], len: 5},
# A fixed sized array (len 5) of string
e: {default: [], schema: {[string], len: 5}, optional: T}
---
# An array with an [] default
a: {array, default: [], optional: T},
# An array with a null default
b: {[string], default: N, optional: T, null: T}
---
# A variable sized array of string with minLen: 3
a: {[string], minLen: 3}
---
# A variable sized array of string witn maxLen:5
a: {[string], maxlen: 5}
---
# A fixed sized array with length 5
a: {[string], len: 5}
---
# An array set to null
a?*: {array, default: N}
# An array that will accept any values.
b: {[], null: T}
---
# Set an array to optional
a?: []
b?: array
# Assign optional value to an array using optional: T
b: {[], optional: T}
# Set an array to option using default and null
c: {[], default: N, null: T, default: T}
---
# Set an array type for a, b, c
a: array
b: {type: array}
c: {type: array, schema:[number]}
---
# Defining an array of numbers
numArray: [number]
---
[63, 45, 66, 80, 74]
# Defining an array of strings
stringArray: [string]
---
[English, Maths, Physics, Computer Science]
# An alphanumeric array with a schema
alphaNumArray: {array, schema: {any, anyOf: [string, int]}}
---
[1, a, 2, b, 3, c]
tags: [string, int]
---
[1, a, 2, b, 3, c]
# An array that will accept mixed values
mixedArray: [ ]
---
[one, T, { a:10, b: -Inf, NaN } ]
# Assigning default: [] to the array of string
~ optionalStringArray?: {[strings], default: [ ]}
---
~ [Eggs, Green salad] # String Array
~ # Default is empty array []
# Assigning default and schema to the array
object?: {array, default: [{N, N}], schema: [{ header*, footer*}]}
---
~ [{Hello, World}] # array of object
~ # default is array of null object
# A fixed sized array of string with len: 5
fixedSizedStringArray: {[string], len: 5}
---
[ Wings of Fire,
Ignited Minds,
Indomitable Spirit,
India 2020,
Turning Points ]
# A variable sized array of objects with maxLen: 4.
address:{
[{street: string, city: string, zip: {string, len: 5}],
maxLen: 4
}
---
[ {Bond street, New York, 50001},
{X street, Hollywood, 30001},
{Maple street, Tennessee, 80007},
{Union street, Montclair, 45003} ]
# Nested array
enggDepartment: [
{deptName: string,
deptSubject: {[string], maxLen: 5}}
]
---
[computer Science, {[data structure, Language Processing]}]
# Two-Dimensional array
matrix: {[{[int], len:3}], len: 3}
---
[[1, 1, 1], [1, 1, 1], [1, 1, 1]]
# Three-Dimensional array
matrix: {[[{[int], len:3}], len: 3], len: 3}
---
[
[[5, 1, 2], [2, 2, 1], [8, 5, 1]],
[[4, 1, 8], [4, 6, 2], [4, 0, 2]],
[[9, 1, 5], [1, 8, 1], [4, 2, 2]]
]
# Defining an url
website: url
---
https://example.com
# valid and Invaliid url
website: url
---
https://example.com # the input will be accepted by the IO parser
Example.com # input will not be accepted as it is not a valid url
# Set the choices for companyWeburl
companyWeburl: {
type: url,
choices: [https://example1.com,
https://example2.com, https://example3.com]
}
---
https://example1.com
# Set pattern for the referenceUrl
referenceUrl: {
type: url,
pattern: 'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+'
}
---
http://example.com, http://example2.com
# int16 type variable
# all the inputs from -32768 to +32767 will be accepted
TestNumber:{type: int16}
---
~ -32750 # valid
~ 12585 # valid
~ 32765 # valid
~ 32768 # invalid
~ -32770 # invalid
Fixed-precision decimal values for financial and high-precision computations
A Decimal in Internet Object represents fixed-precision decimal values designed for applications that require exact numeric calculations, especially financial computations where floating-point precision issues could lead to significant errors. Decimal is a scalar primitive that stores exact numeric values with a defined precision and scale.
Unlike standard floating-point numbers (which may suffer from approximation issues), Decimal values maintain exact precision throughout arithmetic operations, ensuring accurate and predictable results.
A Decimal value is expressed as a number with the m
suffix:
decimal = decimalValue | scientificDecimal
decimalValue = ["-" | "+"] digit+ ["." digit+] "m"
scientificDecimal = decimalValue ("e" | "E") ["-" | "+"] digit+
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
m
Decimal Suffix
U+006D
Identifies value as Decimal
0-9
Digits
Multiple
Standard decimal digits
.
Decimal Point
U+002E
Separates integer and fraction
-
Minus Sign
U+002D
Indicates negative numbers
e
/E
Exponent
Multiple
Scientific notation exponent
123.45m # Fractional decimal
123m # Integer decimal
0.001m # Leading zeros
-789.01m # Negative decimal
1.23e2m # Equivalent to 123m
1.23e-2m # Equivalent to 0.0123m
5e3m # Equivalent to 5000m
Decimal values maintain their precision throughout operations:
0.1m + 0.2m # 0.3m (exact representation)
# Compare with floating-point: 0.1 + 0.2 ≈ 0.30000000000000004
Each Decimal value is defined by:
Precision: Total number of significant digits
Scale: Number of digits after the decimal point
123.45m # Precision: 5, Scale: 2
0.000123m # Precision: 6, Scale: 6
Zero as a decimal:
0m # Zero decimal
0.0m # Zero with scale
123.45 # ❌ Missing 'm' suffix (should be 123.45m)
123.45mm # ❌ Multiple suffixes not allowed (should be 123.45m)
m123.45 # ❌ Suffix must be at the end (should be 123.45m)
.45m # ❌ Must have leading digit (should be 0.45m)
123.m # ❌ Must have trailing digit if decimal point used (should be 123.0m or 123m)
Internet Object preserves:
Exact decimal precision and scale
The chosen representation form (standard vs scientific notation)
Syntactic fidelity (as written, except that an explicit plus sign is not preserved)
However, it does not interpret:
Rounding behavior for operations
Domain-specific precision requirements
Currency or unit semantics
Such semantics are the responsibility of the schema layer, validators, or application logic.
Number Types Overview - Launcher for all number types and formats
Number - For standard floating-point numbers
BigInt - For arbitrary-precision integers
A collection may be created with or without explicitly defining schema definition for the records. However, it is always recommended to define a schema for the collections of records.
A Simple Collection can be created in the data section of the Internet object document by prefixing each record with a tidal sign (~ U+007E)
. It enables the parser to identify the next record when multiple records are sent.
In the Simple Collection as the schema is not defined the type and the structure of collection records can differ.
# Creating a simple Collection
---
~ Ironman, 20, Male, {Bond Street, New York, NY}
~ Spiderman, 25, Male, {Duke Street, New York, NY}, cool
An Explicit Collection is created by explicitly defining the schema for the collection of records. Prefixing schema with the tidal sign (~ U+007E)
enables the parser to understand the multiple records that may be sent according to a particular schema definition.
# Creating an Explicit Collection
~ $address: {street, city, state}
~ $schema: {
name: string,
age: {int, min:28},
gender: {string, choices: [Male, Female]},
$address
}
---
~ Ironman, 20, Male, {Bond Street, New York, NY}
~ Spiderman, 25, Male, {Duke Street, New York, NY}
~ Wonderwoman, 25, Female, {Z street, San Francisco, California}
Here in the code snippet, multiple records are passed in the data section of the document using Collections.
Internet Object DateTime is inspired by the ISO 8601 format. DateTime can be passed as a string and is represented in the following ways, with or without separators.
Date Time format with separator: YYYY-MM-DDThh:mm:ss.SSSZ
Example : 1997-07-16T19:20:30.500+01:00
Date Time format without separator: YYYYMMDDThhmmss.SSSZ
Example: 19970716T192030.500+0100
The DateTime is the string type and therefore there is no need to enclose it in the double quotation mark (" U+0022)
as parser identifies it as a string.
Here, T
is a delimiter used to separate the date
from the time
. The time
portion in the DateTime
object must be preceded by T
. Z
represents the time zone designator (+hh:mm
or -hh:mm
).
Symbol
Represents
Range
Default Value
YYYY
Year
1990, 1991...
-
MM
Date
01, 02 ... 11, 12
01
DD
Month
01, 02 ... 30, 31
01
HH
Hour
00, 01 ... 22, 23
00
mm
Minute
00, 01 ... 58, 59
00
ss
Second
00, 01 ... 58, 59
00
SSS
Millisecond
000, 001 ... 998, 999
000
Symbol
Character
Unicode
Description
-
Hyphen
U+002D
Used to separate parts of the date
:
Colon
U+003A
Used to different parts of time
.
Period
U+002E
Used to separate seconds from milliseconds
T
Alphabet "T"
U+0054
DateTime separator
The Time Zone can be represented as ±hh: mm
or ±hhmm
i.e with or without separators. For example, +00:00
, +0000
or +00
. However, representing -00:00
, -0000
, or -00
is not permitted. While representing a Time Zone, a plus sign must be used for positive zero values and a minus sign for negative values.
Time Zone is written at the end of a DateTime. It is not a separate data type on its own. It can only be passed when both date and time are passed to a DateTime object. "Z"
can be directly added after time without space, where "Z"
is the zone designator for the zero UTC offset. It defaults to Z or Zulu Time or Greenwich mean time (GMT) or +0:00
.
Time Zone with separators:
Time Zone without Separators:
+HH:mm
= +05:30
+HHmm
= +0530
+HH
= +05
+HH
= +05
-HH:mm
= -12:30
-HHmm
= -1230
-HH
= -12
-HH
= -12
Valid date-time representation with separator separating date, time, and time-zone
# DateTime with separators
YYYY-MM-DDTHH:mm:ss.SSSZ = 2020-12-31T12:34:55.675Z # 2020-12-31T12:34:55.675Z
YYYY-MM-DDTHH:mm:ss.SSS = 2020-12-31T12:34:55.675 # 2020-12-31T12:34:55.675
YYYY-MM-DDTHH:mm:ss = 2020-12-31T12:34:55 # 2020-12-31T12:34:55.000
YYYY-MM-DDTHH:mm = 2020-12-31T12:34 # 2020-12-31T12:34:00.000
YYYY-MM-DDTHH = 2020-12-31T12 # 2020-12-31T12:00:00.000
YYYY-MM-DD = 2020-12-31 # 2020-12-31T00:00:00.000
YYYY-MM = 2020-12 # 2020-12-01T00:00:00.000
YYYY = 2020 # parsed as 2020-01-01T00:00:00.000
Valid date-time representation without separator separating date, time, and time-zone.
# DateTime without separators
YYYYMMDDTHHmmssSSSZ = 20201231T123455.675Z # 2020-12-31T12:34:55.675Z
YYYYMMDDTHHmmssSSS = 20201231T123455.675 # 2020-12-31T12:34:55.675
YYYYMMDDTHHmmss = 20201231T123455 # 2020-12-31T12:34:55.000
YYYYMMDDTHHmm = 20201231T1234 # 2020-12-31T12:34:00.000
YYYYMMDDTHH = 20201231T12 # 2020-12-31T12:00:00.000
YYYYMMDD = 20201231 # 2020-12-31T00:00:00.000
YYYYMM = 202012 # 2020-12-01T00:00:00.000
YYYY = 2020 # parsed as 2020-01-01T00:00:00.000
Defining date time in the Internet Object Document.
# Set loginDatetime type as datetime
loginDatetime: datetime
---
~ 2020-01-31T10:34:55.675
~ 20200131T103855.324
Defining date time with timezone in the Internet object Document.
# Set loginDatetime type as datetime
# and pass datetime with timezone
loginDatetimezone: datetime
---
~ 2020-01-31T10:34:55.675+05:30
~ 20200131T103855.324+0530
The DateTime is derived from the String type, hence it shares the same MemberDef as the String. However, DateTime enforces additional constraints with the respective Datetime format and the same is applicable to the DateTime MemberDef.
Apart from the schema, the IO document header can have definitions. The definitions allow you to define schema, variables, metadata, and much more. In essence, the definitions are the collection of key-value pairs, with the following structure.
The definition must start with a tidal symbol (~ U+007E)
followed by a key-value pair. The key-value pair must be separated by a colon (: U+003A)
.
Element
Unicode
Details
~
U+007E
Tilde - Starts the definition
:
U+003A
Colon - Key and Value Separator
Key
N/A
The string key, as defined in the .
Value
N/A
The values as defined in the .
WS
WhiteSpace Char
0 or more white-space character
Simple definitions such as meta-data declaration can be written as shown in the code snippet below.
# The result meta-data
~ pageSize: 1
~ currentPage: 1
~ totalPages: 1
~ recordCount: 2
~ success: T
---
# The data
~ John Done, 25, {Bond Street, New York, NY}
~ Jane Doe, 20, {Bond Street, New York, NY}
Any value defined in the definition section can be used as a variable. The dollar $ prefix can be used to declare schema and/or consume the variable value. If the key starts with $
a sign the variable will be treated as a schema and handled likewise.
# Variables and schema definitions
~ y: yes # value var
~ n: no # value var
~ $address: {street, city, state} # schema var
~ $schema: {name, age, $address, ready:{string, choices:[$y, $n]} # schema var
---
~ John Done, 25, {Bond Street, New York, NY}, $y
~ Jane Doe, 20, {Bond Street, New York, NY}, $y
Here in the code snippet, y: yes
and n: no
are used as value definition similarly keys in the schema prefixed with $
sign represents schema definitions.
Internet Object (IO) is a document-oriented data serialization format designed to optimize data transmission over networks. This specification introduces IO as an alternative to existing formats such as JSON, offering a structured approach to data representation and exchange.
The fundamental structure of IO is an ordered collection of values, analogous to CSV (Comma-Separated Values) but with extended capabilities. These capabilities include support for nested objects, arrays, and inline keys, providing enhanced expressiveness and flexibility.
Document-Oriented Design: In contrast to value-oriented formats, IO adopts a document-centric approach, facilitating the separation of data from definitions to enhance clarity and maintainability.
Ordered Collection with Extended Functionality: IO's core structure maintains an ordered collection of values while supporting complex data structures such as nested objects and arrays.
Schema-First Approach: IO emphasizes schema-first design to ensure data consistency and predictability. While schemas are optional, their inclusion significantly enhances data integrity and validation.
Concise Syntax: The syntax of IO is optimized for readability and efficiency, minimizing data size without compromising clarity.
Metadata Integration: IO documents can incorporate metadata, variables, and multiple schemas within the header section, providing comprehensive context for the data.
The following example demonstrates a basic IO document structure:
This structure illustrates IO's concise syntax and inherent schema support. For comparison, an equivalent JSON representation would be:
IO supports collections and various data types, as demonstrated in the following example:
This example illustrates several key features:
Explicit data type definitions in the schema (string
, int
, bool
)
Nested object structures (address
)
Collection of objects denoted by the tilde (~
) prefix
Correspondence between the order of values and the schema definition
The equivalent JSON representation would be:
This comparison demonstrates IO's capacity to represent structured data collections efficiently, offering a compact and readable format while maintaining an ordered structure.
In many scenarios, it's beneficial to define schemas separately from the data. This approach allows for schema reuse, versioning, and easier maintenance. Here's an example of a separate schema followed by a document using that schema:
Separate Schema (person.io)
Document with Collection and Metadata
In this example:
The schema is defined separately, potentially in a file named "person.io".
The document references the schema URL in its metadata.
The document includes additional metadata such as record count and pagination information.
The collection contains multiple records, each prefixed with ~
.
Each record follows the structure defined in the schema, including an array of skills.
This structure allows for efficient data transmission, as the schema only needs to be sent once and can be cached by the receiving system. It also facilitates easy updates to the schema without necessarily changing the data format.
Internet Object represents a significant advancement in data serialization technology. By combining the simplicity of ordered collections with the robustness of schema-based validation, Internet Object offers a powerful yet accessible solution for modern data exchange needs. Its key strengths include:
Efficiency in data transmission and storage
Clarity through its schema-first approach and document-oriented design
Flexibility in handling various data structures and types
Compatibility with existing JSON-based systems
These attributes make Internet Object suitable for a wide range of applications, from web-based and networked environments to data storage and interchange in diverse domains such as IoT, cloud computing, and enterprise systems.
The subsequent sections of this specification provide comprehensive details on Internet Object's syntax, schema definition language, supported data types, and advanced features. This information will enable developers, system architects, and data engineers to fully leverage the capabilities of Internet Object in their projects and applications.
As data exchange continues to play a crucial role in our interconnected world, Internet Object stands poised to address current challenges and anticipate future needs in data serialization and transmission.
Open strings in Internet Object
An Open String in Internet Object is the simplest string format. It is a sequence of Unicode codepoints not enclosed in any quotes. Open strings are ideal for simple, unstructured text that does not begin or end with whitespace and does not require escaping of special or structural characters.
Open strings are scalar values. They preserve all internal whitespace and Unicode content, but cannot start or end with whitespace.
Open strings begin with any non-whitespace codepoint and end at the first whitespace or structural character, or at the end of the document.
Examples of valid open strings:
Multiple open strings in an object:
Multiline open string (no escaping required):
Whitespace: Open strings cannot start or end with whitespace, but preserve all internal whitespace.
No Escaping: No character escaping is supported. Quotes and other characters are allowed as-is.
Multiline: Open strings can span multiple lines if not interrupted by structural characters.
Comments are not allowed within open strings, but may appear outside or between values as per Internet Object comment rules.
Examples of invalid open strings:
Internet Object preserves:
All Unicode codepoints and internal whitespace as written
The unquoted, open form of the string
It does not interpret or enforce:
Escaping or encoding
Leading/trailing whitespace (disallowed)
Application-specific constraints
Any data type is used to assign any type of value to the variables. It is useful in the case where either the actual type is not known or types are needed to be dynamically assigned. Thus for undefined type, the default type will be always set to any
.
Any type can be defined with the members such as type
, default
, choices
, anyOf
, optional
, and null
. Schema of any
TypeDef should be written as,
The TypeDef schema ensures the validity of any
MemberDefs.
As with most of the types in Internet Object, the first member of typedef is type
. The next snippet shows different ways to define the members a
, b
, and c
as any
.
The second member in the any
typedef is default
. Here is how the default values can be defined.
Here, the default value for a
is Monday
and default value for b
is null
.
The choices
restricts the member to be strictly bound with the unique constant values. If set, the choices must be an array of any type of value. The code snippet shows how choices
can be defined for the any
type.
In some cases, a member must accept different kinds of values. Such as, a number could be a multiple of 3 or a multiple of 5; they could be a string or number but not that of other types; two different formats of the schema. TheanyOf
allows schema designers to define members that can accept different kinds of constrained values. It accepts an array of MemberDef and/or schema and types.
This snippet explains how a
, b
and c
can accept various kinds of values.
When set null
to true, a member can accept null values. Here are some of the ways through which a member of any type can accept null values.
When set optioanl
to true, a member can be marked as optional. Here are some of the ways through which a member of any type can be made optional.
Some of the valid examples of members with any
are...
Special numeric values NaN and Infinity in Internet Object
Special numeric values in Internet Object represent mathematical concepts of "Not a Number" and infinite values. These are used to handle edge cases in numerical computations, such as division by zero or invalid mathematical operations. These values follow IEEE 754 standards and provide a way to represent undefined or infinite results within numeric operations.
Special numeric values are expressed as literal keywords:
Special values have fixed representations:
Special values follow IEEE 754 semantics:
Internet Object preserves:
The exact representation of special values
Negative sign for negative infinity
Syntactic fidelity (as written, except that an explicit plus sign is not preserved)
However, it does not interpret:
The mathematical operations that led to these values
Domain-specific handling of special cases
Comparison or equality semantics
Such semantics are the responsibility of the schema layer, validators, or application logic.
- For standard floating-point numbers
name, age, active, address: {street, city}
---
John Doe, 25, T, {Bond Street, New York}
{
"name": "John Doe",
"age": 25,
"active": true,
"address": {
"street": "Bond Street",
"city": "New York"
}
}
name:string, age:int, active:bool, address: {street:string, city:string}
---
~ John Doe, 25, T, {Bond Street, New York}
~ Jane Doe, 20, T, {Main Street, San Francisco}
[
{
"name": "John Doe",
"age": 25,
"active": true,
"address": {
"street": "Bond Street",
"city": "New York"
}
},
{
"name": "Jane Doe",
"age": 20,
"active": true,
"address": {
"street": "Main Street",
"city": "San Francisco"
}
}
]
# Preson Schema
name:string, age:int, active:bool, address: {street:string, city:string}, skills:[string]
~ schemaUrl: "https://example.com/schemas/person.io"
~ recordCount: 3
~ page: 1
~ totalPages: 1
---
~ John Doe, 25, T, {Bond Street, New York}, [JavaScript, Python]
~ Jane Doe, 30, F, {Main Street, San Francisco}, [Java, C++, Rust]
~ Bob Smith, 28, T, {Park Avenue, Chicago}, [Ruby, Go]
type? : {string, default: any, choices: [any]},
default? : any,
choices? : [any],
anyOf? : [$memberDef],
null? : {bool, default: F},
optional? : {bool, default: F}
---
# Type set to any
a, b: any, c: {type: any}
---
# Set default value for a and b
a?: {any, Monday}, b?: {any, default: N}
---
# Defining choices for member
a: {any, choices: [1, One, 2, Two, 3, Three]}
---
member: {any, anyOf?: [$memberDef, type, schema]}
---
# Can accept multipole of 5 or multiple of 3
a: {any, anyOf: [{int, multipleOf: 5}, {int, multipleOf: 3}]},
# Can accept string or number values
b: {any, anyOf: [string, number]
# Can accept any of two type of address!
c: {any, anyOf: [{city, state}, {street, city, state}]}
---
# Set default value of a, b, c, d to null
a*, b*: any, c: {any, null: T}, d: {any, null: true}
---
# Set a, b, c, and d to optional
a?, b?: any, c: {any, optional: T}, d: {any, optional: true}
---
# The members a, b, and are by default assigned the any type.
a, b, c
# The name is any and default value is null
name: {any, N}
# The numWord can accept any string or number value.
numWord: {any, anyOf: [string, number]}
openString = nonWhitespace (codepoint)*
nonWhitespace = any Unicode codepoint except whitespace
codepoint = any Unicode codepoint except structural characters or document end
(space, tab, etc.)
Whitespace
Multiple
Terminates or invalidates open string start/end
:
Colon
U+003A
Structural character (terminates string)
,
Comma
U+002C
Structural character (terminates string)
{
Open Curly Brace
U+007B
Structural character (terminates string)
}
Close Curly Brace
U+007D
Structural character (terminates string)
[
Open Square Bracket
U+005B
Structural character (terminates string)
]
Close Square Bracket
U+005D
Structural character (terminates string)
"
Double Quote
U+0022
Allowed, does not terminate or need escape
'
Single Quote
U+0027
Allowed, does not terminate or need escape
John Doe
Peter D'mello
जॉन डो
Wow Great
😃
जॉन डो, Wow Great, 😃
Lorem ipsum dolor sit amet consetetur sadipscing elitr sed
diam nonumy eirmod.
Tempor invidunt ut labore et dolore magna aliquyam erat
sed diam voluptua
John Doe # ✗ Starts with whitespace (should be 'John Doe')
John Doe # ✗ Ends with whitespace (should be 'John Doe')
"John Doe" # ✗ Quoted (should be unquoted for open string)
.John # ✗ Starts with a dot (if dot is structural in context)
specialValue = nanValue | infinityValue
nanValue = "NaN"
infinityValue = ["+" | "-"] "Inf"
NaN
Not a Number
Multiple
Represents invalid numeric result
Inf
Infinity
Multiple
Represents infinite value
-
Minus Sign
U+002D
Indicates negative infinity
+
Plus Sign
U+002B
Optional positive indicator
NaN # Not a Number
Inf # Positive infinity
-Inf # Negative infinity
+Inf # Positive infinity (explicit)
NaN # ✅ Standard form
Inf # ✅ Positive infinity
-Inf # ✅ Negative infinity
+Inf # ✅ Explicit positive infinity
# NaN comparisons always return false
NaN == NaN # false
NaN != NaN # true
# Infinity comparisons
Inf > 100 # true
-Inf < 0 # true
nan # ❌ Lowercase not allowed
NAN # ❌ All caps not allowed
inf # ❌ Lowercase not allowed
INF # ❌ All caps not allowed
infinity # ❌ Full word not supported
-NaN # ❌ NaN cannot be signed
Date and time values in Internet Object
Date and Time values in Internet Object are represented using annotated strings that follow ISO 8601-compatible formats. These provide built-in support for temporal data with automatic parsing to native Date objects during deserialization. Internet Object supports three distinct temporal types: dates, times, and combined date-time values.
Date and time values are scalar values that represent temporal data. The content between the quotes must be valid according to their respective format specifications.
dateTimeValue = dateValue | timeValue | dateTimeValue
dateValue = "d" (singleQuotedDate | doubleQuotedDate)
timeValue = "t" (singleQuotedTime | doubleQuotedTime)
dateTimeValue = "dt" (singleQuotedDateTime | doubleQuotedDateTime)
singleQuotedDate = "'" dateContent "'"
doubleQuotedDate = '"' dateContent '"'
Date and time values use specific annotation prefixes followed by quoted content:
```ebnf
dateTimeValue = dateValue | timeValue | dateTimeValue
dateValue = "d" (singleQuotedDate | doubleQuotedDate)
timeValue = "t" (singleQuotedTime | doubleQuotedTime)
dateTimeValue = "dt" (singleQuotedDateTime | doubleQuotedDateTime)
singleQuotedDate = "'" dateContent "'"
doubleQuotedDate = '"' dateContent '"'
singleQuotedTime = "'" timeContent "'"
doubleQuotedTime = '"' timeContent '"'
singleQuotedDateTime = "'" dateTimeContent "'"
doubleQuotedDateTime = '"' dateTimeContent '"'
dateContent = yearPart [monthPart [dayPart]]
timeContent = hourPart [minutePart [secondPart [millisecondPart]]]
dateTimeContent = yearPart [monthPart [dayPart]] ["T" hourPart [minutePart [secondPart [millisecondPart]]]] [timeZone]
yearPart = digit4
monthPart = ["-"] (("0" digit1-9) | ("1" ("0" | "1" | "2")))
dayPart = ["-"] (("0" digit1-9) | (("1" | "2") digit0-9) | ("3" ("0" | "1")))
hourPart = [":"] (("0" | "1") digit0-9) | ("2" ("0" | "1" | "2" | "3"))
minutePart = [":"] (("0" | "1" | "2" | "3" | "4" | "5") digit0-9)
secondPart = [":"] (("0" | "1" | "2" | "3" | "4" | "5") digit0-9)
millisecondPart = "." digit3+
timeZone = "Z" | (("+" | "-") hourPart [minutePart])
The following characters are used to structure date and time values:
d
Date Prefix
U+0064
Indicates date-only value
t
Time Prefix
U+0074
Indicates time-only value
dt
DateTime Prefix
-
Indicates combined date-time value
'
Single Quote
U+0027
Encloses temporal content
"
Double Quote
U+0022
Encloses temporal content
-
Hyphen
U+002D
Date separator (optional)
:
Colon
U+003A
Time separator (optional)
.
Period
U+002E
Millisecond separator
T
Letter T
U+0054
Date-time separator
Z
Letter Z
U+005A
UTC timezone designator
+
Plus Sign
U+002B
Positive timezone offset
-
Minus Sign
U+002D
Negative timezone offset
0-9
Digits
U+0030-U+0039
Numeric components
d'...'
)Examples of valid date values:
d'2024-03-20' # Full date with separators
d'2024-03' # Year and month (day defaults to 01)
d'2024' # Year only (month and day default to 01)
d'20240320' # Full date without separators
d'202403' # Year and month without separators
d"2024-12-31" # Double quotes supported
t'...'
)Examples of valid time values:
t'14:30:45.123' # Full time with milliseconds
t'14:30:45' # Hour, minute, second
t'14:30' # Hour and minute (second defaults to 00)
t'14' # Hour only (minute and second default to 00)
t'143045123' # Without separators
t'143045' # Without separators, no milliseconds
t'1430' # Without separators, hour and minute
t"09:00:00" # Double quotes supported
dt'...'
)Examples of valid datetime values:
dt'2024-03-20T14:30:45.123Z' # Full datetime with timezone
dt'2024-03-20T14:30:45.123' # Full datetime, no timezone
dt'2024-03-20T14:30:45' # Without milliseconds
dt'2024-03-20T14:30' # Without seconds
dt'2024-03-20T14' # Without minutes
dt'2024-03-20' # Date only (time defaults to 00:00:00.000)
dt'20240320T143045123Z' # Without separators
dt'2024-03-20T14:30:45+05:30' # With timezone offset
dt'2024-03-20T14:30:45-08:00' # Negative timezone offset
dt"2024-12-31T23:59:59.999Z" # Double quotes supported
With separators: YYYY-MM-DD
Without separators: YYYYMMDD
Partial formats: YYYY-MM
, YYYY
, YYYYMM
Defaults: Missing month defaults to 01
, missing day defaults to 01
With separators: HH:mm:ss.SSS
Without separators: HHmmss.SSS
Partial formats: HH:mm:ss
, HH:mm
, HH
Defaults: Missing components default to 00
24-hour format: Hours range from 00
to 23
Combined: Date + T
+ Time + optional timezone
Timezone: Z
(UTC) or ±HH:mm
or ±HHMM
Partial: Any valid date format + optional time components
Defaults: Missing time defaults to 00:00:00.000
, missing timezone defaults to Z
Whitespace: Leading and trailing whitespace around quotes are ignored
Separators: Both separated (2024-03-20
) and non-separated (20240320
) formats are supported
Partial Values: Missing components are filled with appropriate defaults
Timezone: If no timezone is specified, UTC (Z
) is assumed for datetime values
Validation: Parser validates format compliance and logical date/time values
Quote Style: Both single and double quotes are supported
Examples of invalid date and time values:
d2024-03-20 # ✗ Missing quotes
d'2024-13-20' # ✗ Invalid month (13)
d'2024-02-30' # ✗ Invalid date for February
t'25:00:00' # ✗ Invalid hour (25)
t'12:60:00' # ✗ Invalid minute (60)
dt'2024-03-20 14:30:00' # ✗ Missing T separator
dt'2024-03-20T14:30:00+25:00' # ✗ Invalid timezone offset
d'2024-03-20T14:30:00' # ✗ Date prefix with time component
t'2024-03-20T14:30:00' # ✗ Time prefix with date component
dt'2024-03-20T14:30:00.123456' # ✗ More than 3 millisecond digits
When processed by an Internet Object parser:
Date values (d'...'
) are parsed to Date objects with time set to 00:00:00.000Z
Time values (t'...'
) are parsed to Date objects with date set to 1900-01-01
DateTime values (dt'...'
) are parsed to complete Date objects
Missing components are filled with appropriate defaults
Invalid formats result in parsing errors
The parsed Date object maintains the exact temporal representation
Internet Object preserves:
The exact format as written (with or without separators)
The choice of single or double quotes
The specific annotation prefix (d
, t
, or dt
)
The timezone information for datetime values
It does not interpret or enforce:
Calendar-specific constraints beyond basic validity
Leap year calculations during parsing (handled by Date constructor)
Business logic constraints (e.g., working hours, holidays)
During parsing:
All temporal values are converted to native date/time objects in the target platform
Date-only values have time components set to midnight UTC
Time-only values have date components set to a reference date (typically 1900-01-01
)
Timezone information is preserved in the resulting date object
Missing timezone defaults to UTC for datetime values
When parsing date-time values from Internet Object format:
DateTime Values (dt'...'
):
Explicit UTC (Z
): dt'2024-03-20T14:30:45.123Z'
→ Represents UTC time
Explicit Offset: dt'2024-03-20T14:30:45.123+05:30'
→ Represents time with specific timezone offset, Indian Standard Time (IST) in this case
No Timezone: dt'2024-03-20T14:30:45.123'
→ Treated as UTC (default behavior)
Date Values (d'...'
):
Always treated as UTC at midnight: d'2024-03-20'
→ 2024-03-20T00:00:00.000Z
No timezone information is preserved or needed for date-only values
Time Values (t'...'
):
No timezone information is applicable for time-only values, will always be treated as UTC.
When converting native date/time objects back to Internet Object format:
Date Objects to DateTime (dt'...'
):
UTC dates: Serialized with Z
suffix → dt'2024-03-20T14:30:45.123Z'
Dates with timezone info: Serialized with appropriate offset → dt'2024-03-20T14:30:45.123+05:30'
Local dates: Should be converted to UTC and serialized with Z
suffix
Date Objects to Date (d'...'
):
Time components are omitted, timezone is not included → d'2024-03-20'
Always represents the date portion regardless of original timezone
Date Objects to Time (t'...'
):
Date components are omitted, timezone is not included → t'14:30:45.123'
Represents the time portion regardless of original timezone
Default Timezone: When no timezone is specified in datetime values, UTC is assumed
Timezone Preservation: Explicit timezone information in datetime values is preserved during round-trip operations
Offset Interpretation: Timezone offsets are interpreted according to ISO 8601 standards
Range Validation: Timezone offsets must be within valid ranges (-12:00
to +14:00
)
Format Support: Both ±HH:mm
and ±HHMM
offset formats are supported during parsing
Serialization Consistency: Serialization should use the ±HH:mm
format for timezone offsets
Parsing Examples:
dt'2024-03-20T14:30:45Z' # → UTC time: 2024-03-20T14:30:45.000Z
dt'2024-03-20T14:30:45+05:30' # → UTC equivalent: 2024-03-20T09:00:45.000Z
dt'2024-03-20T14:30:45-08:00' # → UTC equivalent: 2024-03-20T22:30:45.000Z
dt'2024-03-20T14:30:45' # → UTC time: 2024-03-20T14:30:45.000Z (default)
d'2024-03-20' # → Date: 2024-03-20 (time irrelevant)
t'14:30:45' # → Time: 14:30:45.000 (date irrelevant)
Serialization Examples:
# UTC time: 2024-03-20T14:30:45.000Z
→ dt'2024-03-20T14:30:45.000Z' # DateTime format
→ d'2024-03-20' # Date format
→ t'14:30:45' # Time format
# Time with offset: 2024-03-20T14:30:45.000+05:30
→ dt'2024-03-20T14:30:45.000+05:30' # DateTime format with offset
→ d'2024-03-20' # Date format (timezone ignored)
→ t'14:30:45' # Time format (timezone ignored)
Structural characters define the syntax and organization of data within an Internet Object document. These characters form the foundation of the format's grammar and control how data is parsed and interpreted.
,
Comma
U+002C
Value separator
Separates items in arrays and objects
~
Tilde
U+007E
Record delimiter
Indicates the start of a new record in collections
:
Colon
U+003A
Key-value separator
Separates keys from their corresponding values
[
Open Square Bracket
U+005B
Array start
Begins an array structure
]
Close Square Bracket
U+005D
Array end
Ends an array structure
{
Open Curly Bracket
U+007B
Object start
Begins an object or dictionary
}
Close Curly Bracket
U+007D
Object end
Ends an object or dictionary
---
Triple Hyphens
U+002D
Section separator
Separates header and data sections of the document
#
Hash
U+0023
Comment delimiter
Initiates a single-line comment
"
Double Quote
U+0022
String delimiter
Encloses string values
'
Single Quote
U+0027
String delimiter
Alternative string delimiter
# Surrounding braces define the object
# And key-value pairs are separated by colons and commas
~ { name: "John Doe", age: 30, active: true }
# Array with values surrounded by square brackets
~ [ "item1", "item2", "item3" ]
# Schema definition
~ $person: {name: string, age: number}
# Triple hyphens separate sections
---
# Tilde marks new record in the collection
~ "Alice", 25
~ "Bob", 30
~ "Charlie", 35
{
message1: "Hello World", # Double quotes
message2: 'Hello World', # Single quotes (equivalent)
path: "C:\Program Files\" # Escaped quotes when needed
}
Balanced Delimiters: Opening brackets/braces must have corresponding closing ones
Proper Nesting: Structures can be nested but must maintain proper hierarchy
Separator Consistency: Commas separate elements within the same structure level
Section Division: Triple hyphens (---
) separate document sections
Comment Scope: Hash (#
) comments extend to end of line only
String Equivalence: Single and double quotes are functionally equivalent
Objects: {key: value, key: value}
Arrays: [value, value, value]
Mixed Nesting: Objects and arrays can contain each other
Header Section: Schema definitions and metadata
Data Section: Actual records preceded by ~
Section Separator: ---
divides header from data
Inline Comments: # Comment text
Full Line Comments: # Complete line comment
Documentation: Comments can appear anywhere for annotation
Other Special Characters - Additional functional characters
Literals - Predefined constant values
Comments - Comment syntax and usage
Collections - Collection structure and records
In the Internet Object format, whitespace refers to any character with a Unicode code point less than or equal to U+0020
(i.e., characters in the range U+0000
to U+0020
). This range includes both non-printable control characters and common whitespace characters such as the horizontal tab (U+0009
), newline (U+000A
), vertical tab (U+000B
), form feed (U+000C
), carriage return (U+000D
), and space (U+0020
).
whitespace = ascii_whitespace | unicode_whitespace ;
ascii_whitespace = ? any character with Unicode code point U+0000 to U+0020 ? ;
unicode_whitespace = U+1680 | U+2000 | U+2001 | U+2002 | U+2003 | U+2004
| U+2005 | U+2006 | U+2007 | U+2008 | U+2009 | U+200A
| U+2028 | U+2029 | U+202F | U+205F | U+3000 | U+FEFF ;
In addition to the characters in the range U+0000
to U+0020
, the Internet Object format also includes characters in the Unicode whitespace category as whitespace. This includes characters such as the non-breaking space (U+00A0
), em space (U+2003
), and en space (U+2002
), among others. Including Unicode whitespace characters can make it easier to work with text in languages that use non-Latin scripts, such as Arabic, Chinese, or Japanese.
It's also worth noting that the Internet Object format recognizes the zero-width non-breaking space (U+FEFF
) as whitespace. This character is often used as a byte order mark (BOM) in Unicode-encoded documents.
The following table lists the valid whitespace characters:
U+0000
to U+0020
Space, Line Feed, Carriage Return, Tab, Bell, etc.
Any character having charCode <=0x20
such as space. Includes ASCII space and control characters.
U+1680
Ogham Space Mark
Space used in Ogham scripts.
U+2000
En Quad
Space equal to the width of the lowercase letter "n".
U+2001
Em Quad
Space equal to the width of the uppercase letter "M".
U+2002
En Space
Space equal to half the width of the em space.
U+2003
Em Space
Space equal to the width of the em space.
U+2004
Three-per-Em Space
Space equal to one-third of an em space.
U+2005
Four-per-Em Space
Space equal to one-quarter of an em space.
U+2006
Six-per-Em Space
Space equal to one-sixth of an em space.
U+2007
Figure Space
Space equal to the width of a numeral character.
U+2008
Punctuation Space
Space used for punctuation.
U+2009
Thin Space
Space narrower than the regular space character.
U+200A
Hair Space
Very narrow space used for special purposes.
U+2028
Line Separator
Character used to separate lines in text.
U+2029
Paragraph Separator
Character used to separate paragraphs in text.
U+202F
Narrow No-Break Space
Non-breaking space narrower than the regular space character.
U+205F
Medium Mathematical Space
Space used in mathematical notation.
U+3000
Ideographic Space
Space used in East Asian scripts.
U+FEFF
Byte Order Mark (BOM)
Zero Width Non-Breaking Space, often used as a BOM.
Whitespace Insensitive: Internet Object is not whitespace sensitive, meaning that the parser ignores the whitespaces surrounding the values and structural elements
String Preservation: Any whitespace characters found within the values or strings themselves are preserved
Unicode Code Points: All whitespace characters are recognized based on their Unicode code points
Reserved Characters: All listed whitespace characters are reserved and should not be used as part of identifiers or keys
Enhance Readability: Use whitespace characters like spaces and tabs to format your document for better readability
Avoid Unnecessary Whitespace: While whitespace can improve readability, excessive or unnecessary whitespace can clutter the document
Consistent Formatting: Maintain a consistent use of whitespace throughout the document to ensure uniformity and ease of maintenance
Be Mindful of Invisible Characters: Some whitespace characters, like zero-width spaces, are invisible but can affect the parsing and rendering of the document
Encoding - Unicode character handling and encoding
String Values - Whitespace handling in strings
A TypeDef ("type definition") in Internet Object is the meta MemberDef for a data type. It is a formal Internet Object object that describes all the valid options, constraints, and validation rules for values of that type.
TypeDefs allow Internet Object to:
Define strict, standard, and extensible contracts for each data type
Interpret both positional and keyed members in user MemberDefs
Ensure validation, code generation, and tooling are consistent for every field
TypeDefs themselves use the full Internet Object object syntax—so every rule that applies to IO objects also applies to TypeDefs.
TypeDef: The "contract" or master MemberDef for a type; defines what is valid in MemberDefs for that type.
MemberDef: What schema authors write for fields; always validated against the TypeDef of its declared type.
All rules for IO objects and MemberDefs apply to TypeDefs (keyed/positional, optional, null, etc.).
A TypeDef is written as a valid Internet Object object.
Members are always treated as options (usually optional, unless the type demands otherwise).
Both positional and keyed entries can be defined, following IO object rules.
Conventions like ?
(optional) and *
(nullable) are allowed.
type? : {number, choices: [number, int, int16, int32, byte]},
default? : number,
choices? : [number],
min? : number,
max? : number,
multipleOf? : number,
divisibleBy?: number,
null? : {bool, F},
optional? : {bool, F}
type?: Allowed type(s) for this number MemberDef (including derived types).
default?: Default value for the field (optional).
choices?: Allowed set of values (optional).
min?, max?: Numeric range constraints (optional).
multipleOf?, divisibleBy?: Mathematical constraints.
null?, optional?: Whether value may be null or optional.
TypeDefs support both positional and keyed options, based on the standard IO object rules.
Positional values are interpreted in the order specified by the TypeDef.
Keyed options can be provided in any order after positional values.
For example: The TypeDef for number expects:
1st position: type (number
, int
, etc.)
2nd position: default value
3rd position: choices array
User MemberDefs may use:
age: {number, 20} # type=number, default=20
age: {int16, 20, [10,20,30,40,50]} # type=int16, default=20, choices=[...]
age: {number, min: 10, max: 99} # type=number, min/max set
age: {number, 10, [5,10,15], min:5} # type=number, default=10, choices=[5,10,15], min=5
When a schema author writes a MemberDef for a field (e.g. age: {number, min:10}
), the validator:
Looks up the TypeDef for the declared type (number
).
Interprets any positional values according to their order in the TypeDef.
Checks that all keys used are defined and valid in the TypeDef.
Applies all relevant validation logic and reports any errors.
Invalid MemberDef Example:
age: {number, minimum: 10, maximum: 99} # ❌ invalid: keys not in TypeDef
Valid MemberDef Examples:
age: {number, min: 10, max: 99}
age: {int16, 20, [10, 20, 30, 40, 50]}
age: {number, min: 10, max: 99, null:T}
TypeDef
IO Spec authors
All fields of a type
See example for number above
MemberDef
Schema authors
Individual fields
age: {number, min: 10, max: 99}
TypeDef is always validated as an IO MemberDef.
User-written MemberDefs are always checked against the TypeDef for their type.
If a user provides any key or positional value in a MemberDef that is not present (or allowed) in the TypeDef, the schema will not validate.
For example:
age: {number, minimum: 10} # ❌ Error: "minimum" is not a valid key for number
score: {number, pattern: "\\d+"} # ❌ Error: "pattern" is not a valid key for number
TypeDefs cannot be changed or extended by schema authors.
Only IO spec maintainers can define TypeDefs for core types—ensuring consistency across systems and tools.
Each built-in type's documentation page in the IO spec includes its TypeDef (see "number", "string", "array", etc.).
These are canonical, and are the only source of truth for valid constraints/options for a type.
Q: Can I add new options to a TypeDef for a type in my own schema? A: No. TypeDefs are fixed in the IO spec, ensuring standard validation everywhere.
Q: Can positional values be used for all types? A: Only if the TypeDef for that type defines them in a positional order.
Q: How does the validator know how to interpret my MemberDef? A: It uses the TypeDef for your field's type, and applies both positional and keyed rules accordingly.
Q: Is TypeDef itself an IO object and memberdef? A: Yes—TypeDef uses full Internet Object object/memberdef syntax and is parsed and validated the same way.
MemberDef Reference - How to write MemberDefs for fields
Schema Definition Language - Overview of Internet Object schema syntax
In its simplest form, an object schema can be just a set of keys separated by a comma ","
. Such schema ensures that the object has values for all the required keys. Schema can be defined in the header section of the Internet Object document or maintained separately. The following example shows how easy to create a basic schema-first Internet Object document.
id, department, employeeId, address # The schema
---
02, Marketing, 255, { X Street, New York, NY } # The object
The Internet Object schema does not enforce schema designer to provide the type of the member. If not provided, such members are marked as any
type. That means, they can be assigned any values. For more information see the any datatype.
It is always recommended to define to which datatype members belong. Internet Object members can be assigned any allowed datatype such as string, number, int, int32, int16, byte, email, url, datetime, date, time, bool, object, array, or any.
Defining members with simple types are good in some cases, however, they do not provide a mechanism to create complex constraints. In such cases, the MemberDefs (The member's definitions) are used to create complex type definitions. The memberDefs are objects designed to impose complex constraints on the associated member. For example, the following schema allows the member phrases
to accept string values only if the length is between 20 and 200 characters. It will invalidate the value when the constraint is not match.
phrase: {string, minLen: 20, maxLen: 200}
---
~ A quick brown fox jumps over the lazy dog # Valid value
~ Hello world! # Invalid, len < 20
Meberdef is generally represented by enclosing data types or schema followed by optional comma-separated-values, and conditions: value pairs all inside the curly braces as shown below.
The following example represents a schema with MemberDef.
name: {string, min: 20, max: 100},
age: {int, max: 20},
gender: {string, choices: [Male, Female, NotDisclosed]}
In the above example, the schema has a complex type definition which is created using MemberDef. The variable name
has type
, min
and max
as its members. The variable age
has type
, and max
as its members. Similarly, gender
has type
and choices
as its members.
The above representations are valid and will successfully validate the following object.
Jane Doe, 20, Male
An object schema can be defined with the child objects and arrays schema. The child object defined in the schema definition must be enclosed inside the curly braces.
{
name: string,
age: int,
address: {
street: string,
city : string,
state: string,
zip: int
},
gender: string,
skills: {
default: Null,
array: [strings]
}
}
In the above example, the key variable address
has a child object having four keys i.e street
, city
, state
and zip
. Similarly, the key skills
is defined with an array schema having a default value null
and array
of type strings
.
The above representations are valid and will successfully validate the following object.
{
Jane Doe, 20, { X Street, New York, NY, 10005 },
[Leadership, Problem-Solving]
}
Internet object documents may have multiple schemas. The document containing multiple schemas can be reused and/or nested to reduce code length in such a case the schema must be defined before use.
The schema must be prefixed with a dollar sign ($
U+0024
) before reusing the schema in the multiple schemas definitions. So that the parser will identify the schema variable and will map values to the respective keys according to the Schema Definition.
Schema Definition represents the collection of key-value pairs declared using schema in the header section of the document. For more details refer to Definitions.
~ $address: {street, city, state}
~ $personalDetails: {
name: string,
age: int,
$address,
isActive: bool,
remark: string
}
In the above example, the address
schema is represented using a dollar sign ($
U+0024
), so that it can be reused inside another schema personalDetails
.
~ $address: {city, zipCode, state}
~ $person:{
name,
age,
currentAddress: $address,
permanentAddress: $address
}
~ $accountDetails: {
personDetails: $person,
AccountNo:int
}
---
In the above example, the header section has three schemas i.e address
, person
and accountDetails
. The address
schema is used inside the person
schema and person
schema is used inside the accountDetails
schema making the schema representation nested.
The above representations are valid and will successfully validate the following object.
{
Jane Doe, 20, { X Street, New York, NY, 10005 },
{ Hills Street, Lake Peekskill, NY, 10537 }, 12344564567
}
To map values from the data section to the variables in the header, the parser will first check the header section for the default schema definition that starts with the word "schema"
. Once the parser finds out the default schema, all values will be checked by matching them with the variables. If they are matched then they will be mapped to the schema variables.
If the values are not matched with the variables the parser will check for the other schema definition.
~ $address: {street, city, state}
~ $Schema: {
name: string,
age: int,
$address,
isActive: bool,
}
---
John Doe, 25, {X-street, California, US}, T
In the above example, the parser will first check the header part for the schema definition with the word "schema"
. Once it is found it will start validating all the variables in the schema i.e name,
age
, address
, and isActive
to the values in the data section if it matches then it will be mapped successfully.
If the header section of the document does not contain schema definition and only contain the value definition and/or meta-data as shown in the example below. The values will be mapped to the positioned variables after getting the values from the value variable.
~ pageSize: 1
~ currentPage: 1
~ totalPages: 1
~ y: Yes
~ n: No
---
~ John Doe, 25, $y, {X-street, California, US}
~ Bob Redwood, 36, $n, {blue-street, New Jersey, US}
{
"0": "John Doe",
"1": 25,
"2": "Yes",
"3":{ "0": "X-street",
"1": "California",
"2": "US"
},
}
{
"0": "Bob Redwood",
"1": 36,
"2": "No",
"3":{ "0": "blue-street",
"1": "New Jersey",
"2": "US"
},
}
If the header section in the document is empty, then the parser will map all values in the data section to the respectively positioned variables.
---
John Doe, 25, {X-street, California, US}
{
"0": "John Doe",
"1": 25,
"2":{ "0": "X-street",
"1": "California",
"2": "US"
},
}
If the header section does not contain a definition and only contains schema. In such a case the parser will map the values to schema variables as shown in the example below.
name, age, address: {street, city, state}
---
John Doe, 25, {X-street, California, US}
{
"name": John Doe,
"1": 25,
"address":{ "street": X-street,
"city": California,
"state": US
},
}
A schema may contain the optional and nullable key. The key can be set to optional
by suffixing it with a question mark (?
U+003F
). Similarly, the key can be set to null by suffixing it with an asterisk(*
U+002A
).
name: string,
gender?*: {string,
null: true,
optional: true,
choices: [Male, Female]
},
age?: {int, optional: true, max: 20}
In the above example, the defined schema contains both nullable and optional keys. The key gender
is set to optional
as well as null
and key age
is set to optional
.
The Data Section in an Internet Object Document is where the actual data resides. An internet Object document can have one or more Data Section. It consists of one or more sections, each defined by a separator line (---
) and optionally accompanied by a section name and schema. The data itself can be represented as either a single object or a collection of objects, allowing for a flexible and structured approach to data representation. Following diagram shows the structure of the Data Section.
Each Data Section begins with a separator line (---
), which organizes the document into distinct sections. The separator line can include optional elements:
Section Name: Identifies the section and its purpose.
Schema Name: Defines the structure or constraints of the data, prefixed with $
.
ℹ️ The separator line must end with a newline character (
\n
) orEoF
(End of File).
The separator line can take on various forms for different levels of detail, each ending with a newline character (\n
) or EoF
(End of File):
Without Name and Schema: The simplest form, just the separator (---
).
With Section Name: The separator followed by a section name (--- employee
).
With Section Name and Schema: The separator followed by a section name and a schema name, separated by a colon (--- employee : $employee
).
With Only Schema: The separator followed by just the schema name (--- $employee
).
Omitting Section Name: In a multi-section document, the section name can be omitted only once. When omitted, the section name will be derived from the associated schema (e.g., --- $employee
implies that the section name is employee
).
Default Section Name and Schema: If both the section name and schema are omitted, the section name will default to data
, and a default schema will be used.
Unique Section Names: Each section in an Internet Object Document must have a unique section name. Duplicate section names are not allowed.
It is the simplest form of the separator line. It will use the default section name (data) and the default schema set for the document.
---
~ John Doe, 25, Male, {Bond Street, New York, NY}, [agile, swift]
~ Jane Doe, 20, Male, {Duke Street, New York, NY}
Here the section name is employee
. The schema will be the default schema set for the document.
--- employee
~ John Doe, 25, Male, {Bond Street, New York, NY}, [agile, swift]
~ Jane Doe, 20, Male, {Duke Street, New York, NY]
Here the section name and schema are both are explicitly mentioned as employee
and $employee
respectively.
--- employee : $employee
~ John Doe, 25, Male, {Bond Street, New York, NY}, [agile, swift]
~ Jane Doe, 20, Male, {Duke Street, New York, NY]
Here only the schema is mentioned. The section name will be derived from the schema name (employee). However, if the document the section name is already used, then it will be an error.
--- $employee
~ John Doe, 25, Male, {Bond Street, New York, NY}, [agile, swift]
~ Jane Doe, 20, Male, {Duke Street, New York, NY}
After the separator line, the data within a section is introduced. This data can either be a single object or a collection of objects. The flexibility in data representation allows the Internet Object Document format to handle various types of information efficiently.
Objects are structured data entities composed of key-value pairs. Each object is defined within curly braces {}
and can contain nested objects or other data types, forming a hierarchical structure.
Collections represent a list of objects, making it possible to include multiple records within a single Data Section. Each object within a collection is defined in the same way as a standalone object but is part of a broader collection context.
A single object can be represented after the separator.
---
John Doe, 25, Male, {Bond Street, New York, NY}, [agile, swift]
It is not necessary to have a section separator for a single section document if there is no header or schema. Hence, the above example can be written as:
John Doe, 25, Male, {Bond Street, New York, NY}, [agile, swift]
A collection is represented by listing objects, each prefixed with ~
on separate lines:
---
~ John Doe, 25, Male, {Bond Street, New York, NY}, [agile, swift]
~ Jane Doe, 20, Male, {Duke Street, New York, NY}
You can have an empty data section. An empty data section can be represented by just the separator line without any data.
---
It is not necessary to have a section separator for an entirely empty document.
An Internet Object Document can include multiple sections, each with its own data:
--- $library
# Bookville Library
City Central Library, "123 Library St, Bookville"
--- $books
~ The Great Gatsby, "F. Scott Fitzgerald", 1234567890, T, [Fiction, Classic], 1925
~ "1984", George Orwell, 2345678901, F, [Fiction, Dystopian], 1949, { user123, d"2024-02-20"}
--- subscribers: $users
~ user123, John Doe, Standard, [{2345678901, d"2024-01-20"}]
~ user456, Jane Smith, Premium, []
The Data Section, organized by separators and structured using objects and collections, offers a robust and flexible method for handling data within Internet Object Documents. This structure ensures that the documents are clear, consistent, and effective for a wide range of applications.
The Internet Object document promotes reusability through variables. It allows defining variables that can be applied to simplify schema and definitions, obfuscate values, or reduce the data size. Every key defined in the definition section can be used as a variable.
Internet Object variables can be categorized into two groups.
Value Variables
Schema Variables
The Value variables are used to directly access and reuse values.
In the above snippet records
, y
, n
, and rgb
are the value variables.
The schema variables start with $
sign and it is used to directly access and reuse schema.
In the above code snippet, the schema variable address
is reused in another schema variable named person
.
The value variables and schema variables enable the reuse of definition.
Variables are also used for hiding critical information with modified content to enforce data protection and security.
The following example demonstrates how one can pass critical information over the internet using variables.
The above code snippet represents secrectKey
as s
and activationKey
as a
saved on the client-side. This information is securely passed over the internet using variables as shown below,
The receiver will receive the following information without compromising on data security.
The use of variables helps to reduce the code size as it enables definition reuse that ultimately reduces bandwidth utilization.
In the above code snippet, the schema variable address
and accountDetails
are used in the person
schema definition. So, rather than creating a similar schema multiple times for address
it can be created once and reused multiple times in the document.
Variables improve schema readability by grouping similar and reusable codes and limiting line length.
Arrays in Internet Object
An Array in Internet Object represents an ordered collection of values enclosed in square brackets. Arrays are scalar containers used to express lists, sequences, and multi-dimensional tabular structures.
Each value in an array may be:
A primitive (string, number, boolean, null),
A structured value (object or another array).
Internet Object arrays are syntactically compact, support nesting, and avoid ambiguity by enforcing strict value presence and disallowing trailing or elided elements.
An array begins with [
and ends with ]
, containing zero or more comma-separated values.
In the above grammar, value
refers to any valid Internet Object value as defined in the . The exact syntax and behavior of each value type (e.g., strings, numbers, booleans, objects, arrays, null) are defined separately in their respective type specifications.
Whitespace is permitted around elements and structural characters for readability.
All forms with equivalent value structure are interpreted identically.
An empty array is written as:
This represents a valid array with no elements.
Arrays may contain other arrays, allowing arbitrarily deep structures.
Comments are allowed around and within arrays, as long as they comply with Internet Object's general comment syntax.
Comments must not break value boundaries. Embedded comment styles (like inside strings or object keys) are not permitted.
Internet Object preserves:
Value order
Whitespace (non-significant in interpretation)
Syntactic fidelity (as written)
However, it does not interpret:
The meaning of order
Whether values must be unique
Such semantics are the responsibility of the schema layer, validators, or application logic.
Derived from String, the Internet Object Date is an ISO 8601 compatible date format. It can be represented as YYYY-MM-DD
or YYYYMMDD
i.e It can be passed with or without separators (- U+002D).
It prescribes a minimum four-digit year format from a range 0000
to 9999
to avoid the year 2000
problem. However, years from a range 1583
to 9999
are automatically allowed by a standard, while years prior to 1583
can only be used by mutual agreement of the partners in information interchange.
Here is the code snippet demonstrates, how to define and use date type.
The Date is derived from the String type, hence it shares the same as the String. However, Date enforces additional constraints with respective date format and the same is applicable to the Date MemberDef.
When a variable is classified as an int
then it will accept all the integers including signed and unsigned integers. It will not accept float values.
The Integer must be represented using one or more ASCII digits (0 U+0030
to 9 U+0039
), prefixed with or without the minus sign (- U+002D)
. The integer must not contain a decimal point as some language validators will accept it and some will not.
The int
is derived from the number type that shares the sameas the Number i.e type
, default
, choices
, max
, min
, multipleOf
, divisibleBy
, optional
and null
while enforcing the additional constraint that the number must be of integer type.
# Defining value variables
~ record: 123
~ y: yes
~ n: no
~ rgb: [red, green, blue]
---
# Defining schema variables
~ $address: {
street: string,
zip: {string, maxLength: 5},
city: string
}
~ $person: {
name: string,
age: int,
homeAddress?: $address,
officeAddress?: $address
}
---
# Reusing value variable and schema variable
~ y: yes
~ n: no
~ rgb: [red, green blue]
~ $address: {
street: string,
zip: {string, maxLength: 5},
city: string }
~ $person: {
name: string,
age: int,
seniorCitizen: {choices: [$y, $n]}
color: {string, choices: $rgb},
homeAddress?: $address,
officeAddress?: $address
}
---
Spiderman, 25, $n, red, {Queens, 50010, New York}, {Bond Street, 50001, New York}
# Reusing value variable and schema variable
~ $person: {
name: string,
age: int,
seniorCitizen: {choices: [yes, no]}
color: {string, choices: [red, green, blue},
homeAddress?: {
street: string,
zip: {string, maxLength: 5},
city: string
},
officeAddress?: {
street: string,
zip: {string, maxLength: 5},
city: string
}
}
---
Spiderman, 25, no, red, {Queens, 50010, New York}, {Bond Street, 50001, New York}
# Key saved on the client side
~ s: ghhhj456nhghhhy11569bbbgtxxcv123654897
~ a: jk889456llkhynnnk12364lkkkhuk4125336nk
# Information passed on the server
~ y: yes
~ n: no
~ rgb: [red, green blue]
~ $address: {city, zipCode, state}
~ $person: {
name,
age,
currentAddress: $address,
permanentAddress: $address
}
~ $accountDetails: {
name,
phoneNo,
currentAddress: $address,
secretKey, activationKey
}
---
Spiderman, 7855423656, {Queens, 50010, New York}, $s, $a
# Information Received by the receiver
{
name: "Spiderman",
phoneNo: 7855423656,
currentAddress:{
city: "Queens",
zipCode: 50010,
state: "New York"
}
secretKey: "ghhhj456nhghhhy11569bbbgtxxcv123654897",
activationKey: "jk889456llkhynnnk12364lkkkhuk4125336nk"
}
# Reduce the code length by facilating code reuse
~ rgb: [red, green blue]
~ $address: {
street: string,
zip: { string, maxLength:5 },
city: string
}
~ $accountDetails: {branchName:string, accountNo, IFSCcode}
~ $person: {
name: string,
age: int,
bankaccountInfo: $accountDetails,
color: { string, choices: $rgb },
homeAddress?: $address,
officeAddress?: $address
}
---
{ Spiderman, 25, red,
{Queens, 50010, New York},
{Bond Street, 50001, New York}
}
array = "[" [ value *("," value) ] "]"
[
Open Square Bracket
U+005B
Starts an array
]
Close Square Bracket
U+005D
Ends an array
,
Comma
U+002C
Separates values within array
[] # Empty array
[apple, banana, cherry] # String values
[1, 2, 3] # Number values
[T, F, N] # Boolean and null values
[{x:1}, {y:2}] # Array of objects
[1, [2, 3], [4, [5, 6]]] # Nested arrays
[[1,2],[3,4]] # 2D array
[ a , b , c ] # Valid
[]
[1, [2, 3], [[4]]]
[
1, 2, # inline comment
3
]
[a, b, ] # ❌ Trailing comma
[a,,c] # ❌ Elided value
[ , ] # ❌ Missing value
[,a] # ❌ Starts with comma
[a b c] # ❌ Missing separators
[a, b] # ✅ Valid
[a, null, c] # ✅ Use null for missing values
# Set testNumber to int
testNumber: int
---
~ 101254666452 # valid
~ -12125987566459963311323664566130236 # valid
~ 12546632.4254563 # invalid
~ 20.0 # invalid
~ 123645.2536 # invalid
Internet Object Schema Specification
Internet Object schemas define the structure (“shape”) of objects in IO documents. Unlike verbose, map-based standards, IO schemas use the same concise object syntax as actual data, making them both human-friendly and machine-tractable.
Internet Object schemas are designed for clarity, expressiveness, and minimalism. They avoid the verbosity of traditional schema languages (like JSON Schema or XML Schema) by using the same syntax for both data and schema. This makes it easy for humans to author, read, and maintain schemas, while keeping them fully machine-tractable for validation, tooling, and interoperation with other formats.
Schemas describe:
Field names (and order, if needed)
Types and constraints
Nesting and composition
Optional and dynamic fields (by convention)
A schema is written using the Internet Object object syntax:
Fields are comma-separated: name, age, address
Each field can be:
Just a name (defaults to “any” type)
Typed (name: string
)
Nested (address: { street: string, city: string }
)
Constrained (score: {int, min: 0, max: 100}
)
Fields may be marked as optional or dynamic using conventions (see “Semantic Field Modifiers”).
# Minimal schema (all fields are "any" type)
name, age, address
# Typed schema
name: string, age: int, isActive: bool
# Nested schema
address: { street: string, city: string }
# Typed with constraints (MemberDef)
name: {string, maxLen: 100}, age: {int, min: 0, max: 120}
Top-level schemas may use the open object form (no braces): name, age, address
Nested objects (schemas for nested fields) must use { ... }
: address: { street: string, city: string }
Keyed fields: Schema and data map fields by name (name: value
).
Unkeyed (positional) fields: Supported for compact, CSV-like data. Recommendation: Use positional mapping only when all fields are required and unambiguous.
Unkeyed fields can appear before any keyed fields.
Once a keyed field appears, all remaining fields must be keyed.
Nested objects: Use { ... }
for fields whose value is itself an object.
Reusable schemas: Named with $
in the schema header; referenced as $name
.
~ $address: {street: string, city: string}
~ $user: {name: string, age: int, address: $address}
Field
name
Unkeyed field, type is any
Typed Field
name: string
Keyed field, explicit type
Constraint
age: {int, min: 0, max: 120}
With constraints
Optional
remark?
Field may be omitted
Nullable
address*
Field may be null
Dynamic
*, *: string
Allow extra fields
Nested
address: { street: string, city: string }
Nested object
Reusable
$address
Reference to a named schema
schema = objectEntries
objectEntries = memberDef *( "," memberDef )
memberDef = [key] [fieldModifier] [":" typeOrDef]
key = string
fieldModifier = "?" | "*" | "?*"
typeOrDef = type | memberDef | ref
type = "string" | "int" | "bool" | "object" | "array" | ...
ref = "$" name
Note: Modifiers and complex memberDefs are conventions, not core grammar.
Internet Object supports the following built-in types:
string
, int
, bool
, float
, number
, object
, array
, and domain-specific types (date
, datetime
, etc.)
Types may be extended or customized in a future version by user-defined type systems.
min / max / minLen / maxLen: For numbers, strings, arrays.
choices: For enums. Example: {string, choices: [A, B, C]}
pattern: For regex constraints on strings. Example: {string, pattern: "^[a-z]+$"}
default: Assigns a default value if missing.
Internet Object schemas use the following conventions (not syntax) for special field semantics:
Optional: Suffix ?
on field name (e.g., age?
). Means the field may be omitted in data.
Nullable: Suffix *
(e.g., remark*
). Means the field can be null
.
Dynamic/extra fields: Use *
at end (e.g., name, age, *
or *: string
).
These are interpreted by schema tooling, not by the object parser itself.
Optional (?
): Field can be omitted from the data object. If omitted, its value is undefined unless a default is provided.
Nullable (*
): Field can explicitly be set to null
.
Both (?*
): Field can be omitted or set to null
.
Examples:
email?: string # May be omitted
nickname*: string # May be null
bio?*: string # May be omitted or null
*
at the end of a schema allows extra fields not specified in the schema.
*: type
constrains the type of all extra fields.
Example:
name: string, *, # Allow any extra fields
*: int # All extra fields must be int
For strict validation and best interoperability, avoid *
unless required.
For positional schemas, avoid optionals except at the end.
Keyed schemas map directly to “properties” in JSON Schema, Avro, etc.
Optionals (?
) are omitted from "required"
arrays.
Dynamic fields (*
) map to additionalProperties
.
Constraints map to field-level attributes in target schema (e.g., minLength, enum).
Recommendation: For robust tooling and validation, always canonicalize Internet Object schemas to a fully-keyed, explicit, and type-complete form internally. This enables safe mapping to and from JSON Schema, Avro, or other industry formats.
foo: string
{ "foo": { "type": "string" } }
age?: int
{ "age": { "type": "integer" } }, "required": []
*, *: string
additionalProperties: true
or { "type": "string" }
{ foo: {string, minLen:2} }
{ "foo": { "type": "string", "minLength": 2 } }
A subset of Internet Object schemas and data are directly compatible with JSON and JSON Schema.
For full compatibility, use quoted keys and JSON-legal values.
Prefer explicit types for all fields in production schemas.
Use fully-keyed schemas for anything beyond trivial/CSV-like records.
Use optionals only at the end if using positional mapping.
Document and canonicalize mixed or dynamic schemas for robust tooling.
Flat (CSV-like): name, age, score
Typed object: name: string, age: int, score: float
Nested: user: {name: string, address: {city: string}}
Optional/nullable: comment?: string, timestamp*: datetime
Dynamic: *, *: string
Internet Object allows you to define fields that can accept any object or any array using open forms:
{}
Use {}
as a schema for a field that may contain any object, regardless of fields or structure.
This matches objects of any shape, including empty objects.
meta: {} # 'meta' can be any object, equivalent to `meta: object`
payload?: {} # 'payload' is optional, any object allowed
data: object # 'data' can also be written as `data: {}` for any object
[]
extras: [] # 'extras' can be any array. Same as `extras: array`
tags?: [] # 'tags' is optional, any array allowed
choices: array # 'Can also be written as `choices: []` for any array'
Use []
as a schema for a field that may contain any array, regardless of element type or length.
This matches all arrays, including empty arrays.
extras: [] # 'extras' can be any array
tags?: [] # 'tags' is optional, any array allowed
Useful for fields where you expect unstructured, arbitrary data (e.g., “metadata,” “extension,” “blob,” or raw API fields).
No validation is performed on object keys or array elements—only the container type is enforced.
To restrict the allowed content, use typed or constrained schemas:
[int]
for an array of integers
{ name: string }
for an object with required fields
[ { name: string } ]
for an array of objects with shape
{}
Any object (no structure required)
[]
Any array (no type/length required)
[type]
Array of the specified type
[MemberDef]
Array validated by MemberDef
[{...}]
Array of objects with defined shape
Note: These open forms can also be used in MemberDefs for fields that may contain arbitrary objects or arrays.
**Summary:**
- Put this new section right after “Common Schema Patterns” and before your “Full Example.”
- This order introduces specific patterns, then the open (most general) forms, then illustrates usage in a complete example.
## **Full Example**
### **Complete Schema Example with Comments**
```ruby
# User schema
name: string, # Required
age?: int, # Optional
email: {string, pattern:"^[^@]+@[^@]+$"}, # Required, pattern constraint
isActive: bool, # Required
address?: { # Optional nested object
street: string,
city: string,
zip?: int # Optional zip code
},
*: string # Allow extra string fields
Valid Data:
{
name: John Doe,
isActive: T,
address: {
street: Bond Street,
city: New York
},
nickname: Johnny
}
(Refer to your object.md
for formal object syntax and EBNF.)
See [object.md] for formal definition; include diagrams or syntax trees as appendix if desired.
*
and ?
are schema conventions—they do not change object syntax.
All schema fields are mapped to data fields using either position (unkeyed) or name (keyed).
For compatibility, always provide a canonical, fully-keyed, fully-typed version of the schema for external tooling.
Can I mix positional and keyed fields? Yes, but only unkeyed fields before any keys. Once a key is present, all subsequent fields must be keyed.
What happens if a required field is missing? Validation fails unless the field is optional (?
) or has a default.
Are keys case-sensitive? Yes. "Name"
and "name"
are distinct.
How are unknown fields handled? If *
is present in the schema, unknown fields are accepted (and optionally typed); otherwise, they are rejected by validators.
Schema evolution, migration, backward compatibility best practices can be addressed in future versions.
Value
Description
Optional
Default
Example
YYYY
Four-digit decimal number
(0000-9999
)
No
-
2020
MM
two-digit decimal number (01-12
)
Yes
01
04
DD
two-digit decimal number (01-31
)
Yes
01
30
Date with separators:
Date without Separators:
YYYY-MM-DD
= 2020-02-17
YYYYMMDD
= 20200217
YYYY-MM
= 2020-02
YYYYMM
= 202002
YYYY
= 2020
YYYY
= 2020
# Defining date for registeredDate
registeredDate: date
---
~ 2020-09-17
~ 20200917 # parsed as 2020-09-17
~ 2020-09 # parsed as 2020-09-01
~ 2019 # parsed as 2019-01-01
A number type can be defined with the members such as type
, default
, choices
, min
, max
, multipleOf
, divisibleBy
, optional
and null
. Schema of the number TypeDef should be written as,
The TypeDef schema ensures the validity of number
MemberDefs.
The first member of the typedef is type
. The number can be of type number
or its derived types i.e int
, int16
, int32
, byte
. Here the next snippet shows how the number
type and its derived types can be defined.
The second member in the number
typedef is default
. Here is how the default values can be defined for a number.
Rules for default:
The default value is applicable only if no other value is provided for the key.
If for a key, null is set to true then it must be replaced by its default value.
The default value when set must match with the data type of a key.
The choices
can be added to member variables in numbers so that the input values are restricted to the fixed set of available choices. Choices must be an array of numbers. The code snippet shows how to add choices.
The max
represents the maximum value of a key, that must be a number. The numeric instance max
is valid only if its value is less than or equal to the value of the max
. Here is the snippet that shows how to set max
value for a number.
The min
represents the minimum value of a key, that must be a number. The numeric instance min
is valid only if its value is greater than or equal to the value of the min
. Here is the snippet that shows how to set min
value for a number.
The multipleOf
is used to restrict the value to multiples of a given number. The Value of multipleOf
must be a positive integer. The code snippet shows how to restrict the input value to the multiple of the desired number.
The divisibleBy
is used to restrict the value to divisible by of a given number as shown below.
The member of a number type can be set to optional
. Here is the code snippet that demonstrates how a number can be set to optional.
A number when set to null: true
will accept null values. The snippet below shows how to set a nullable number.
Here are some of the examples that demonstrate how to define number member definition.
Base64 byte strings in Internet Object
A Base64 Byte String in Internet Object is a sequence of binary data encoded in Base64 format, prefixed with b
and enclosed in either single quotes (' U+0027
) or double quotes (" U+0022
). Byte strings are ideal for representing binary data such as images, encrypted content, cryptographic keys, or any arbitrary sequence of bytes in a text-based format.
Base64 byte strings are scalar values that represent binary data. The content between the quotes must be valid Base64 encoding according to RFC 4648.
A Base64 byte string is prefixed with b
and enclosed in either single or double quotes. The content must be valid Base64 encoding.
The following characters are used to structure Base64 byte strings:
Note: Only valid Base64 characters are allowed within the quotes. Invalid characters will result in a parsing error.
Examples of valid Base64 byte strings:
Whitespace: Leading and trailing whitespace around the quotes are ignored. Internal whitespace within the Base64 content is not allowed.
Empty Representation: Empty byte strings are supported (b''
or b""
).
Case Sensitivity: The prefix must be lowercase b
. The Base64 content is case-sensitive as per RFC 4648.
Padding: Proper Base64 padding with =
characters is required for correct decoding.
Validation: The parser validates that the content is valid Base64 and can be decoded to binary data.
Examples of invalid Base64 byte strings:
Internet Object preserves:
The exact Base64 encoding as written
The choice of single or double quotes
The lowercase b
prefix
It does not interpret or enforce:
The format or structure of the decoded binary data
Application-specific constraints on the binary content
Compression or encoding within the binary data
When processed by an Internet Object parser:
The Base64 content is decoded into a sequence of bytes
The resulting binary data is typically represented as a byte array or buffer
Invalid Base64 content results in a parsing error
The decoded data maintains the exact binary representation
A MemberDef (Member Definition) is the core way to define the type, validation rules, and constraints for a single value in an Internet Object schema. With MemberDefs, you can precisely control how each field is validated, using concise and powerful Internet Object syntax.
Every MemberDef is strictly validated against its type's , ensuring schema correctness and interoperability.
A MemberDef is an IO object that defines:
The type of a value (e.g., number
, string
, object
, array
)
Any validation rules, constraints, or options for that value (e.g., min
, max
, choices
, etc.)
Optional default value, nullability, or optionality (using positional values and conventions)
Only options and positional values defined in the for that type are valid in MemberDefs.
A MemberDef is always a { ... }
object in Internet Object format, typically with:
Type as the first value (by position or as a type:
key)
Positional values (like default or choices, if supported by the TypeDef)
Keyed options (like min:
, max:
, pattern:
, etc.)
Examples:
Add ?
for optional: age?: {number, min: 10}
Combine: score?*: {number, min: 0}
Use positional values for default and choices if the TypeDef for that type supports it.
Always against the official for the type.
Only keys and positions listed in the TypeDef are valid.
If you use an invalid key or value, validation fails.
Tip: Always consult the before adding constraints/options.
Use the schema:
key to define validation for nested object or array types:
While Object Schemas and MemberDefs share { ... }
syntax, their purpose and parsing are different:
MemberDef: Validates a single value or field using type and constraints (the focus of this page)
Object Schema: Defines the shape of an object (what keys/fields it has, not how a value is validated)
An Object Schema is a map of field names to types or MemberDefs, specifying the shape of objects, e.g.:
Object Schemas do not add constraints to individual values—they define what fields exist and their types or schemas.
Because both use { ... }
syntax, it's easy to mix them up. Let's look at two lines:
Key distinction:
MemberDef: If first value is a type, or if type
/schema
is a member, it's a MemberDef.
Object Schema: Otherwise, it's just a field map.
Is the first value a known data type? → Yes: MemberDef → No: Go to 2
Contains type
or schema
as a member? → Yes: MemberDef → No: Object Schema
Using options not in the TypeDef: Wrong: age: {number, minimum: 10}
Mixing constraints with object schemas: Wrong: {username: string, maxLen: 16}
(ambiguous!) Right: username: {string, maxLen: 16}
inside an object schema
Omitting the type: Always start with the type in a MemberDef
Use MemberDefs for all fields needing type and/or validation.
Use Object Schemas to describe the field structure of nested objects only.
Use positional values (default, choices) only if defined in the TypeDef for the type.
Always cross-reference the .
Q: Can I use both forms together? A: Yes—use Object Schema for nested structure, MemberDef for each field (even nested).
Q: What if my MemberDef contains a nested schema? A: Use schema: { ... }
inside the MemberDef for deep validation.
Q: What error do I get if I use the wrong form or invalid key? A: Validation fails, usually with a "type mismatch" or "unexpected/invalid field" error, depending on context and TypeDef.
Q: Where do I find all valid options for each type? A: See the .
— all allowed options for each type
name: string,
age: int,
address: {
street: string,
city: string,
state: string,
zipCode: int
},
isActive: bool,
remark: string
type? : {number,
choices: [number, int, int16, int32, byte]},
default? : number,
choices? : [number],
min? : number,
max? : number,
multipleOf? : number,
divisibleBy?: number,
null? : {bool, F}
optional? : {bool, F}
# Set type to number
a: {type: number}
# OR
a: number
---
# Defining number derived types
# Set type to int
a: int,
# Set type to int16
b: int16,
# Set type to int32
c: int32,
# Set type to byte
d: byte,
---
# Assign default value for a as 1.
a: {number, default: 1, optional: T}
# Set b with a null default
b: {number, default: N, optional: T, null: T}
---
# Adding choices
a: {number, choices: [234, 245, 456, 324]}
---
# Set max: 25 for a number
a: {number, max: 25}
---
# Set min: 3 for a number
a: {number, min: 3}
# Set member def multipleOf: 5 for number
a: {number, multipleOf: 5}
---
# Set member def divisibleBy: 5 for a number
a: {number, divisibleBy: 5}
---
# Set number to optional
a?: number
# Assign otional: true to number
a?: {number, optional: true}
# Set number to optional using optional and null
a?: {number, default: N, null: T}
# Set number to null
a*: {number, null: true}
# Add choices to subjectCode
subjectCode: {number, choices: [234, 245, 456, 324]}
# Set max value for age
age: {number, max:25},
---
~ 18 # valid
~ 25 # valid
~ 35 # invalid as the value is greater than max value
# Set min value for age
age: {number, min: 18},
---
~ 25, Male # valid
~ 17, Male # invalid
# Set multipleOf: 5 for the input value of rollNo
rollNo: {number, multipleOf: 5}
---
~ 10 # valid
~ 25 # valid
~ 30 # valid
~ 95 # valid
~ -10 # valid
~ 34 # invalid
~ 12 # invalid
# Set divisibleBy: 12 for a rollNo
rollNo: {number, divisibleBy: 12}
---
~ 48 # valid
~ 60 # valid
~ 96 # valid
~ 120 # valid
~ -36 # valid
~ 8 # invalid
~ 55 # invalid
#Set age to optional
age?: {type: number, default: 1, optional: true, max: 30}
# Set age to null
age*: {type: number, default: 1, null: true, max: 30}
# Set age to optional with default: 1 and max: 30
age?*: { number,
default: 1,
optional: true,
null: true,
max: 30}
---
~ 20 #valid
~ 30 #valid
~ N #valid
~ 15 #valid
base64String = "b" (singleQuotedBase64 | doubleQuotedBase64)
singleQuotedBase64 = "'" base64Content "'"
doubleQuotedBase64 = '"' base64Content '"'
base64Content = { base64Character }
base64Character = "A" | "B" | "C" | ... | "Z" | "a" | "b" | ... | "z" | "0" | "1" | ... | "9" | "+" | "/" | "="
b
Byte Prefix
U+0062
Indicates Base64 byte string type
'
Single Quote
U+0027
Encloses Base64 content
"
Double Quote
U+0022
Encloses Base64 content
A-Z
Uppercase Letters
U+0041-U+005A
Base64 alphabet
a-z
Lowercase Letters
U+0061-U+007A
Base64 alphabet
0-9
Digits
U+0030-U+0039
Base64 alphabet
+
Plus Sign
U+002B
Base64 alphabet
/
Forward Slash
U+002F
Base64 alphabet
=
Equals Sign
U+003D
Base64 padding character
b'SGVsbG8gV29ybGQ=' # "Hello World" in Base64
b"SGVsbG8gV29ybGQ=" # Same as above with double quotes
b'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==' # PNG image data
b'QWxhZGRpbjpvcGVuIHNlc2FtZQ==' # "Aladdin:open sesame" in Base64
b'' # Empty byte string
b"" # Empty byte string (double quotes)
b'TWFu' # "Man" in Base64
b'TWE=' # "Ma" in Base64 (with padding)
b'TQ==' # "M" in Base64 (with padding)
bSGVsbG8= # ✗ Missing quotes
b'SGVsbG8 gV29ybGQ=' # ✗ Space within Base64 content
b'SGVsbG8@V29ybGQ=' # ✗ Invalid character '@' in Base64
b'SGVsbG8' # ✗ Invalid Base64 (missing padding)
b'SGVsbG8gV29ybGQ' # ✗ Invalid Base64 (incomplete)
B'SGVsbG8gV29ybGQ= # ✗ Missing closing quote
b''SGVsbG8gV29ybGQ='' # ✗ Double quotes around content
# Type: number, min/max range
age: {number, min: 10, max: 99}
# Type: number, default: 20 (positional)
age: {number, 20}
# Type: int16, default 20, choices [10,20,30]
age: {int16, 20, [10, 20, 30]}
# Type: string, regex pattern
name: {string, pattern: "^[A-Za-z]+$"}
# Type: object with nested schema
meta: {object, schema: {
author: string,
version: {int, min: 1}
}, default: {author: "Unknown", version: 1}}
# Valid MemberDefs with various types and constraints
age: {number, min: 10, max: 99}
# With 20 as default value
age: {number, 20}
# With choices [10,20,30,40,50] and default 20
age: {int16, 20, [10, 20, 30, 40, 50]}
# With constraints and nullability set specifically
age: {number, min: 10, max: 99, null: T}
age: {number, minimum: 10, maximum: 99} # ❌ 'minimum'/'maximum' not valid for number
age: {number, length: 10} # ❌ 'length' not valid for number
meta: {object, schema: {author: string, version: int}, required: ["author"]}
tags: {array, items: string, minLen: 1}
address: { street: string, city: string }
address: { street: string, city: string } # Object Schema (declares fields/shape)
age: { int, min: 0, max: 120 } # MemberDef (type and constraints)
flowchart TD
A["{ ... }"] --> B{Is first value a known data type?}
B -- Yes --> C[MemberDef]
B -- No --> D{Contains 'type' or 'schema' as member?}
D -- Yes --> E[MemberDef]
D -- No --> F[Object Schema]
Objects in Internet Object
Objects are a fundamental element in Internet Object documents, providing a clear and intuitive way to represent structured data.
An object is expressed as a sequence of values (and key/value pairs) separated by commas (,
U+002C
). For simplicity, clarity, and ease of reading, Internet Object supports two modes for objects:
Open Objects — do not require curly braces and are allowed only at the top level.
Closed Objects — are enclosed in {}
and may appear at any level.
Objects may contain:
Sequential (unkeyed) values
Inline keyed values (key: value
)
A combination — but only if unkeyed values appear before any keys
All values in an object are accessed by position (0-based). If a value has a key, it may also be accessed by key — especially when a schema is applied.
Once a keyed value appears, all subsequent values must also be keyed. Mixing unkeyed values after a key is invalid.
🧩 Design Note: In the early stages of its design, Internet Object was envisioned as a compact, expressive serialization format focused on transmitting structured objects across the internet. The name “Internet Object” was born out of this object-oriented serialization model — structurally similar to formats like JSON.
As the format evolved, it adopted a document-oriented approach, enabling richer representation through sections, schemas, metadata, and stream-friendly constructs. However, the object remains the core unit of structure, and the compact syntax continues to reflect its original vision.
⚙️ Implementation Note: In many programming languages, the term Object
refers to a built-in or base type. To avoid conflicts, libraries and parsers implementing Internet Object may use a distinct class or type name such as InternetObject
. For example, in JavaScript:
const obj = new InternetObject()
Here, obj
is an instance of a class that represents an Internet Object — conforming fully to the object syntax and behavior defined in this specification.
object = "{" [ objectEntries ] "}"
objectEntries = [ unkeyedSegment [ "," keyedSegment ] ]
unkeyedSegment = unkeyedValue *( "," unkeyedValue )
keyedSegment = keyedValue *( "," keyedValue )
unkeyedValue = value
keyedValue = key ":" value
key = string
value = any valid Internet Object value
objectOpen = objectEntries
Keys must be valid strings. Values must be valid Internet Object values. Once a keyed value appears, no unkeyed values may follow.
{
Open Curly Bracket
U+007B
Begins a closed object
}
Close Curly Bracket
U+007D
Ends a closed object
:
Colon
U+003A
Separates keys from values
,
Comma
U+002C
Separates values or key–value entries
John Doe, 25, T
{John Doe, 25, T}
John Doe, age: 25, gender: M
{
John Doe,
25,
isActive: T,
address: {Bond Street, New York, NY}
}
{
name: John Doe,
age: 25,
gender: M,
isActive: T
}
{
"name": John Doe,
'isActive': T,
address: {Bond Street, New York, NY}
}
The following Internet Object is also a valid JSON object:
{"name": "John", "age": 30, "isActive": true}
Keys are double-quoted strings and all values use standard JSON types.
Child objects must always be enclosed in curly braces
{}
. Only the top-level object may use the open form. All nested or embedded objects must use closed object syntax.
~ name: John, Doe, 25 # Unkeyed values after a key
~ {a: 1, b} # Unkeyed value follows keyed entry
~ {1, 2, x: 3, y: 4, 5} # Final value is unkeyed
Whitespace is allowed and ignored:
{ name : John , age : 25 }
{} # ✅ Valid
Empty value positions (via ,,
) are valid:
John Doe,,true,,{NY}
Trailing commas are allowed and ignored:
John, 25, T,,,,
Comments are allowed between entries or alongside values:
{
name: John, # name of person
age: 25, # years old
isActive: T
}
Comments must not appear inside string literals or values.
All values are accessed by their position (0-based).
If a key is provided, the value may also be accessed via key, especially when schema is applied.
Keys do not affect the value’s index position.
Once a key appears, all following values must be keyed.
Keys are optional but must be well-formed strings.
Internet Object preserves:
Value order and keyed/unkeyed structure
Whitespace (non-significant)
Optional comments
It does not enforce:
Key uniqueness
Key-based access without schema
Required presence of keys
The Internet Object format uses UTF-8 as the default and mandatory encoding for all text representation. This ensures universal compatibility and reliable interchange of data across different platforms, systems, and programming languages.
UTF-8 encoding is mandatory for all Internet Object implementations for the following reasons:
Universal Compatibility: UTF-8 is supported by virtually all modern systems and programming languages
ASCII Compatibility: All ASCII characters (0-127) are represented identically in UTF-8
Full Unicode Support: Can represent all Unicode characters and symbols
Byte-Order Independence: No endianness concerns unlike UTF-16 and UTF-32
Self-Synchronizing: Corruption in one character doesn't affect parsing of subsequent characters
While UTF-8 is mandatory, implementations may optionally support additional encodings for specific use cases:
UTF-8
Mandatory
Default and required for all implementations
UTF-16
Optional
May be useful for systems with native UTF-16 support
UTF-32
Optional
Fixed-width encoding, larger file sizes
ASCII
Optional
Subset compatibility (limited to basic characters)
ISO-8859-1
Optional
Legacy support for Latin-1 character set
Internet Object fully supports the Unicode character set through UTF-8 encoding:
Basic Multilingual Plane (BMP): U+0000 to U+FFFF
Supplementary Planes: U+10000 to U+10FFFF
Private Use Areas: Supported but implementation-specific
Control Characters: Handled according to Unicode standards
Recommended Form: NFC (Normalization Form Canonical Composed)
Parser Behavior: Should handle all normalized forms correctly
String Comparison: Implementations should normalize for consistent comparison
Storage: Internal representation may use any normalized form
UTF-8 BOM: EF BB BF
(U+FEFF) at the beginning of files
Parser Behavior: BOM is treated as whitespace and ignored during parsing
Recommendation: BOM is optional and not required for UTF-8
Compatibility: Including BOM won't cause parsing errors
# File with BOM (invisible to parser)
{
name: "Example with BOM",
content: "This file starts with UTF-8 BOM"
}
UTF-8 Detection: Automatically detect UTF-8 encoding
BOM Handling: Skip UTF-8 BOM if present at file start
Error Handling: Provide clear errors for invalid UTF-8 sequences
Normalization: Consider Unicode normalization for string operations
Validation: Validate character sequences according to Unicode standards
UTF-8 Output: Always generate valid UTF-8 sequences
BOM Decision: Consistently include or exclude BOM based on target system
Character Encoding: Properly encode all Unicode characters
Escape Sequences: Generate escape sequences for control characters when needed
Validation: Verify output contains valid UTF-8 before writing
Internet Object recognizes these whitespace characters:
Space: U+0020 (ASCII space)
Tab: U+0009 (horizontal tab)
Line Feed: U+000A (LF, \n)
Carriage Return: U+000D (CR, \r)
Form Feed: U+000C (FF, \f)
All standard line ending conventions are supported:
Unix/Linux: LF (\n
)
Windows: CRLF (\r\n
)
Classic Mac: CR (\r
)
Mixed: Combinations are handled gracefully
Printable Range: U+0020 to U+007E (ASCII printable)
Control Characters: U+0000 to U+001F, U+007F to U+009F
Handling: Control characters in strings must be properly escaped
Null Character: U+0000 should be avoided in text content
Encoding Declaration: Specify UTF-8 encoding in file metadata when possible
File Extension: Use .io
extension to indicate Internet Object format
BOM Consistency: Be consistent about BOM usage within a project
Validation: Validate UTF-8 encoding before processing
Always UTF-8: Use UTF-8 for maximum compatibility
Line Endings: Allow any line ending style during parsing
Character Validation: Validate character sequences are legal Unicode
Encoding Detection: Implement robust encoding detection mechanisms
Escape Sequences: Use standard escape sequences for maximum interoperability
Surrogate Pairs: Properly handle UTF-16 surrogate pairs in escape sequences
Private Use: Define handling of private use area characters
Noncharacters: Decide treatment of Unicode noncharacter code points
Overlong Encoding: Reject overlong UTF-8 sequences
Internet Object Structure - Overall document structure
String Values - String representation and escaping
Comments - Comment syntax and Unicode support
Other than regular string, raw string, and open string, a string can be passed as an Internet email as it is predefined in the parser. The email format is derived from the HTML 5.1-Forms Email syntax recommended by W3C. Internet Object Email Format does not follow the RFC-5322 email representation as it is too strict to implement for the users.
Email format follows the syntax specified in the HTML 5.1 W3C recommendation under section 4.10.5.1.5.
The code snippet shows how to define an email-id
in the Internet Object Document.
# Defining an Email
userEmail: email
---
[email protected]
# Using derived type email to pass email Information
Subject: {
string,
From: string,
To: string, senderEmail: email,
reciverEmail: email
}
---
{
An official Email,
John Doe, Alex Wick,
[email protected],
[email protected]
}
The Email is derived from the String type, hence it shares the same MemberDef as the String. However, Email enforces additional constraints with the respective email format.
The choices
can be added to member variables in the email so that it is restricted to the fixed set of available choices. Choices must be an array of valid emails. Here, the snippet shows how to add choices for the string subtype email.
# Assign choices for a companyEmail.
companyEmail: {
type: email,
choices: [[email protected], [email protected],
[email protected], [email protected]]
}
---
[email protected]
User may specify pattern
for the email by defining pattern
as shown in the snippet below.
# Set pattern for referenceEmail with type email.
referenceEmail: {
type: email ,
pattern: '[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$'
}
---
~ [email protected]
~ [email protected]
Collections in Internet Object
A Collection in Internet Object is an ordered sequence of collection items (objects) within a section of a document. Collections enable efficient serialization, batching, and streaming of multiple objects—such as datasets, tables, or event logs—in a concise, flexible format.
Collections are conceptually similar to datasets in CSV, streams in JSON Lines, or record arrays in Avro.
Collections are always part of an Internet Object document, not standalone documents. An Internet Object document consists of a header and a body. The body contains one or more sections. A section can contain either a single object or a collection (multiple objects as collection items).
Collections support both homogeneous and heterogeneous data. Each item in the collection is independent; failure of one item does not affect others.
A collection section consists of one or more collection items, each beginning with a tilde ~
(U+007E
) followed by an object.
object
is as defined in the . Both open and closed object forms are permitted, though open form is recommended for clarity.
A collection item is the top-level object immediately following a tilde (~
) in a collection section.
Each collection item must be a valid Internet Object object—either in open form (comma-separated values) or closed form (enclosed in {}
).
If the item is empty (~
alone), it is called an empty item and is interpreted as an empty object ({}
).
If a collection item appears syntactically to be a single primitive value (number, string, boolean, null) or an array, it is implicitly promoted to an open object containing that value as its only field.
Examples:
Rule: Every collection item is parsed as an object, regardless of whether it appears to be a primitive, array, or explicit object.
Whitespace is allowed around the tilde, commas, and within objects.
Collection items are typically separated by newlines, but any whitespace may be used.
Trailing commas within objects are allowed and ignored.
An empty item (just ~
) is always interpreted as an empty object ({}
).
If a schema is present, an empty item is valid only if all fields are optional or nullable; otherwise, it is invalid.
Each collection item must be a top-level object (open or closed).
Objects may contain nested arrays or child objects as fields.
Each collection item (object) is parsed and validated independently:
If a collection item fails to parse or validate, only that item is marked as an error.
All other items remain unaffected and are processed as usual.
Implementations may provide modes for "fail fast" (stop on first error) or "parse all" (continue and collect errors); it is recommended to parse all items and report errors per item.
If a collection item contains nested child objects, failure means the entire top-level object (the collection item) is in error, not just the child.
Example:
The third item is invalid, but the others are unaffected.
Collection item order and structure are preserved as written.
Whitespace and comments are preserved (but ignored for parsing).
Interpretation, key uniqueness, and field mapping are determined by schemas, validators, or application logic.
Internet Object allows passing extra values in the dynamic record using an asterisk sign (* U+002A)
without explicitly defining them in the schema definition.
It is invalid to pass extra values in the record without using "*"
sign in the schema definition.
In the above example, extra values are passed without using a "*"
sign which is invalid.
In order to send the extra values in the dynamic record, the "*"
sign must be placed after the last field in the schema as shown in the example below.
In the above example placing the "*"
sign after the last kay field enables the parser to map extra values to the positioned number as,
The above example shows that the extra values passed in the second record are mapped to positions 5
and 6
respectively.
Extra values can be passed using key-value pair in the data section and using"*"
in the header.
In the above example, extra values are passed using key-value pairs. The values will be mapped to the respective keys defined in the schema as well as in the record as shown below,
The TypeDef can be defined for the extra values in the schema. So that the values can be passed according to TypeDef.
The values must be passed according to the TypeDef defined in the schema otherwise it will throw an error.
The values will be mapped to the respective keys defined in the schema as shown below,
In the above example, the extra values must be of string type thus passing other values are invalid.
The schema constraints can be defined for the extra values in the schema. So that the values can be passed accordingly.
The values must be passed according to the defined constraints in the schema otherwise it will throw an error.
The values will be mapped to the respective keys defined in the schema as shown below,
In the above example the request id: "12"
is a string but the minimum length is less than that defined in the schema constrain hence it becomes invalid.
While defining a schema the object is not required to be wrap in the curly braces unless it is a child object or the schema of an array. As the schema is the valid object the same is applicable to the schema.
The schema may be wrapped in curly braces. While defining the schema, key members must be enclosed in the curly braces if the number of members is more than one.
In the above example, the address will only contain street
; city
and state
are independent keys. To add street
, city
and state
in the address
, it must be included in the curly braces as shown below,
Curly braces are optional if the associated schema accepts less than two values.
In the above example, line no 9
is invalid as the number of values passed for the address schema is more than one. The z-street, California
must be included in the curly braces as, {z-street, California}
The multiple optional and nullable members in the same schema should be defined with care as it may lead to invalid mapping.
In the above example, the street
is optional
. Value Mumbai
is passed for the city but it will be assigned to street
.This is because, if the value is passed it will be first assigned to optional
key. Therefore it is essential to define schema carefully while using optional keys.
Many time a member in the schema need to accept values from multiple types. One option would be to use any
type so that members can accept any value. However, the best option is to use anyOf
the constraint provided by the any
type. In the following example, the member test
can accept any string or number value.
collection = collectionItem *(collectionItem)
collectionItem = "~" object
~
Tilde
U+007E
Begins a new collection item
,
Comma
U+002C
Separates values within an object
{}
Curly Braces
U+007B
, U+007D
For closed object syntax (optional)
~ 1 # Interpreted as: { 1 }
~ true # Interpreted as: { true }
~ [a, b, c, d] # Interpreted as: { [a, b, c, d] }
~ John Doe # Interpreted as: { John Doe }
~ {1, 2} # Remains: { 1, 2 }
~ # Empty item, parsed as: {}
~ name: John Doe # Interpreted as: { name: John Doe }
~ 101, Thomas, 25, HR, {Bond Street, New York, NY}
~ # Empty item; parsed as {}
~ 102, George, 30, Sales, {Duke Street, New York, NY}
~ {Jane Doe, 20, f, N/A, [0xFF0000, 0x0000FF], F}
~ {"name": " John Doe", "address": {"street": "Main St", "city": "Seattle"}, "favorite_colors": ["purple"], "is_active": true}
~ {"name": "Eve", "age": 33, "gender": "female", "location": {"city": "Dallas", "state": "TX"}, "favorite_colors": ["orange"], "is_active": false}
~ Dave, 40, m, {Main St, Seattle, WA}, [purple], T
~ {Eve, 33, f, {Elm St, Dallas, TX}, [orange], F}
# ✗ Missing tilde
101, Thomas, 25, HR, ...
# ✗ Missing commas between values, all values are considered as a single value
~ 101 Thomas 25 HR ...
# ✗ Missing comma between values
~ 101, 25 HR, ...
# ✗ Trailing data outside object
~ {101, 25, HR} extra
~ John, 28, m, {Main St, LA}, [red], T # valid
~ Jane, N/A, f, {Second St, LA}, [blue], F # valid
~ Alice, OOPS, f, {Third St, NY, [green], T # Error: ❌ unclosed object, invalid
~ Bob, 35, m, {Fourth St, NY}, [yellow], T # valid
{
name: John Doe,
age: 30,
address: { street: Grant Road,
city: Mumbai,
state: Maharashtra,
zip: 400007
},
isActive: T
}
{
name: Alex,
age: 25,
address: { street: Elphiston Road,
city: Mumbai,
state: Maharashtra,
zip: 400007
},
isActive: T,
5: Male,
6: Cool
}
name, age, address, isActive, *
---
{
John Doe, 30, Mumbai, T, nature: cool, available: T,
requestid: 122120
}
{
name: John Doe,
age: 30,
address: Mumbai,
isActive: T,
nature: cool, # valid
available: T, # valid
requestid: 122120 # valid
}
name, age, address, isActive, *: string
---
John Doe, 30, Mumbai, T, nature: cool, requestid: 122120
{
name: John Doe,
age: 30,
address: Mumbai,
isActive: T,
nature: cool, # valid
requestid: 122120 # invalid
# as the defined type for extra values is string
}
{
name, age, address, isActive,
*: {string, maxLen:20, minLen: 4}
}
---
{
John Doe, 30, Mumbai, T, nature: cool,
department: Human Resource, requestid: "12"
}
{
name: John Doe,
age: 30,
address: Mumbai,
isActive: T,
nature: cool, # valid
department: Human Resource, # valid
requestid: "12" # invalid as minimum lenth of string is 4
}
name, age, address: street, city, state, isActive #invalid
name, age, address: {street, city, state}, isActive #valid
~ $schema: {
name,
age,
address:{street?, city?, state?},
isActive
}
---
~ John Doe, 30, Elphiston street, T #valid
~ Thomas, 24, z street, California, T #invalid
~ Roy, 22, {River Street, London}, T # valid
~ Alex, 25, {X street, Los Angeles, LA}, T # valid
~ $schema: {
name,
age,
address:{street?, city, state?},
isActive
}
---
~ John Doe, 30, Mumbai, T #invalid
~ Roy, 22, {River Street, London}, T # valid
test: {any, anyOf:[string, number]}
---
~ One # valid
~ 1 # valid
~ Two # valid
~ Three # valid
~ 2 # valid
~ 3 # valid
~ $address: {street, city, state}
~ $schema: {name, $address, isActive, * }
~ John Doe, {Red Street, Phoenix, US}, T # valid
~ Alex, {Carnival Street, San Fransisco, US}, T, Male # valid
~ Bob, {Green Street, Los Angeles, US}, T, Cool # valid
# First batch of the record
~ Oliver, {Alpha Street, Denver, Colorado}, T, "77858"# valid
~ Max, {Hill Street, Jacksonville, Florida}, T, 789445 # valid
~ James, { Elm Street, Los Angeles, California}, T, 24 # valid
# Second batch of the record
~ $address: {street, city, state, zip}
~ $schema: {name, age, $address, isActive}
---
# valid as no extra values are passed
~ John Doe, 30, {Grant road, Mumbai, Maharashtra, 400007}, T
# Invalid as extra values are passed
~ Alex, 25, {Elphiston Road, Mumbai, Maharashtra, 400007}, T, Male, cool
~ $address: {street, city, state, zip}
#now it is valid to pass extra values using '*'sign
~ $schema: {name, age, $address, isActive, * }
---
~ John Doe, 30, {Grant road, Mumbai, Maharashtra, 400007}, T # valid
~ Alex, 25, {Elphiston Road, Mumbai, Maharashtra, 400007}, T, Male, cool # valid
Overview of value types in Internet Object
Internet Object supports a rich set of value types that represent different kinds of data. Values are the fundamental building blocks of Internet Object documents, ranging from simple scalar values like numbers and strings to complex structured values like objects and arrays.
All values in Internet Object are designed to be:
Human-readable: Easy to read and write by humans
Machine-parseable: Efficiently processed by computers
Type-safe: Clear distinction between different data types
Expressive: Rich enough to represent complex data structures
Internet Object values are organized into several categories:
Scalar values represent single, atomic pieces of data:
Numbers - Numeric values including integers, floats, and special numeric types
Strings - Text data with various encoding and formatting options
Booleans - True/false values
Null - Absence of value
Base64 Byte Strings - Binary data encoded as Base64
Date and Time - Temporal values with ISO 8601 compatibility
Structured values contain other values and provide organization:
Internet Object provides several string types to handle different text scenarios:
"text"
or 'text'
Standard quoted strings with escape sequences
General text, user input, formatted content
unquoted text
Strings without quotes
Simple identifiers, natural language
r"text"
or r'text'
Literal strings without escape processing
File paths, regex patterns, code snippets
Internet Object supports various numeric types for different precision and range requirements:
42
, 3.14
, 1e10
Standard floating-point numbers
IEEE 754 double precision
42n
, 0x1ABn
Arbitrary precision integers
Unlimited
42.5m
, 3.14159m
High-precision decimal numbers
Configurable precision
NaN
, Inf
, -Inf
Non-finite numeric values
IEEE 754 special values
Internet Object provides built-in support for date and time values:
Date
d'2024-03-20'
Date-only values
d'2024-03-20'
, d'2024'
Time
t'14:30:45'
Time-only values
t'14:30:45.123'
, t'09:00'
DateTime
dt'2024-03-20T14:30:45Z'
Combined date and time
dt'2024-03-20T14:30:45.123Z'
For binary data representation, Internet Object uses:
Base64 Byte Strings (b'SGVsbG8='
) - Efficient encoding of binary data as text
Here's a quick reference of value syntax in Internet Object:
# Scalar Values
42 # Number
"Hello, World!" # Regular string
'Single quotes work too' # Regular string
unquoted string # Open string
r"C:\Users\file.txt" # Raw string
true # Boolean
false # Boolean
null # Null
b'SGVsbG8gV29ybGQ=' # Base64 byte string
d'2024-03-20' # Date
t'14:30:45' # Time
dt'2024-03-20T14:30:45Z' # DateTime
# Structured Values
{ # Object
name: "John Doe",
age: 30,
active: true
}
[1, 2, 3, "four", true] # Array
Internet Object maintains strict type boundaries:
No implicit conversion: Values retain their declared types
Explicit parsing: Type conversion happens during parsing based on syntax
Validation: Type constraints are enforced during processing
Preservation: Original format and type information is maintained
Values can be accompanied by:
Comments: # This is a comment
Whitespace: Flexible spacing and indentation
Line breaks: Multi-line value formatting
{
# User information
name: "John Doe", # Full name
age: 30, # Age in years
# Contact details
email: "[email protected]"
}
Internet Object values support:
Unicode: Full Unicode character set (UTF-8 encoding)
Escape sequences: Standard escape codes in regular strings
Raw representation: Literal character preservation in raw strings
Normalization: Unicode normalization for consistent processing
Scalar Types: Numbers • Strings • Booleans • Null • Binary Data • Date & Time
Text Data: String Types - Regular, Open, and Raw strings
Numeric Data: Number Types - Standard, BigInt, Decimal, and Special values
Temporal Data: Date and Time - Dates, times, and datetimes
Binary Data: Base64 Byte Strings - Encoded binary content
Internet Object Structure Overview - Understanding the overall document structure
Schema Definition Language - Type definitions and validation
Best Practices - Guidelines for effective Internet Object usage
A string type can be defined with the members such as type
, default
, choices
, pattern
, minLen
, maxLen
, len
, optional
, and null
. Schema of the string TypeDef should be written as,
type? : {
string, choices: [string, email, url, datetime, date, time]
},
default? : string,
choices? : [string]
pattern? : string,
minLen? : {int, min: 0},
maxLen? : {int, min: 0},
len? : {int, min: 0}
optional?: {bool, F}
null? : {bool, F}
The TypeDef schema ensures the validity of string
MemberDefs.
The first member of the typedef is type
. The string can define with a type string
or its derived types i.e email
, url
, datetime
, date
, time
. Here the next snippet shows, how the string type and its derived types can be defined.
# Defining string type
a: string, b: {type: string}
---
# Defining string derived types
# Set type to email
a: email, b: {type: email}
# Set type to url
a: url, b: {type: url}
# Set type to datetime
a: datetime, b: {type: datetime}
# Set type to date
a: date, b: {type: date}
# Set type to time
a: time, b: {type: time}
---
The second member in the string
typedef is default
. Here is how the default values can be defined for a string.
# A string with default: Monday
a: {string, default: Monday, optional: T},
# A string with a null default
b: {string, default: N, optional: T, null: T}
---
The default value is applicable only if no other value is provided for the key.
If for a key, null is set to true then it must be replaced by its default value.
The default value when set must match with the data type of a key.
The next member in the string
typedef is choices
. If set, the choices must be an array of strings. Here the snippet shows how the choices
can be added to member variables in a string so that it is restricted to the fixed set of available choices.
# Add choices for the member
a: {string, choices: [abc, "123", "MH4458"]}
---
The value of the pattern
must be a String. The string value passed should be a valid Regular Expression. The data will be then validated according to the Regular Expression and passed accordingly. Regular Expression can be defined in the schema by using pattern
in the schema of a string.
Different versions of schema can be created and executed for patterns in the programming environment. But to remain compatible with the host environment, it is better to stick to the constraints described below.
A single Unicode character, other than the special characters specified below matches itself.
(.
U+002E
): Matches any character except newline character (U+000A
).
(^
U+005E
): Matches only at the start of the string.
($
U+0024
): Matches only at the end of the string.
(...
): Assembles the sequence of regular expressions into a single regular expression.
(|
U+007C
): Matches the regular expression either preceding or following with the "|"
symbol.
[abc]
: Matches any of the characters enclosed by the square brackets.
[a-z]
: Matches the range of characters enclosed by the square bracket.
[^abc]
: Matches any character not in the list.
[^a-z]
: Matches any character out of the given range.
(+
U+002B
): repeats the preceding regular expression one or more times and is greedy as they match as many items as possible.
(*
U+002A
): repeats the preceding regular expression zero or more times and greedy as they match as many items as possible.
(?
U+003F
): makes the preceding regular expression optional. Greedy, matches zero or one preceding regular expression.
+?
, *?
, ??
: The *
, +
, and ?
qualifiers are used to match as much text as possible which is not always desired.
(?!x
), (?=x
): Negative and positive lookahead.
{x}
: Match exactly x occurrences of the preceding regular expression.
{x,y}
: Match at least x and at most y occurrences of the preceding regular expression.
{x,}
: Match x or more occurrences of the preceding regular expression.
{x}?
, {x,y}?
, {x,}?
: Lazy versions of the above expressions.
# Set pattern for the input string
a: {string, pattern:'^(\+[0-9]{3})?[0-9]{10}$'}
---
The value of maxLen
must be a non-negative integer. The string instance is valid only if the number of characters in the string will be less than or equal to the value of maxLen
. Here is the snippet showing how to assign maxLen.
# Assign maxLen:30 for input string
a: {string, maxLen: 30}
---
The value of minLen
must be a non-negative integer. The string instance is valid only if the number of characters in the string will be greater than or equal to the value of minLen
. Here is the snippet showing how to assign minLen.
# Assign minLen:3 for input string
a: {string, minLen: 3}
---
The value of length represented as len
must be a non-negative integer. The string instance is valid only if the number of characters in the string will be equal to the value of len
. The code snippet shows how to assign len
.
# Assign len: 9 for the input string
a: {string, len: 9}
---
The member of a string type can be set to optional. Here is the code snippet that demonstrates how a string can be set to optional.
# Set a to optional
a?: string
# Assign optional: true for a
a?: {string, optional: true}
A string when set to null: true
will accept null values. The snippet below shows how to set a nullable string.
# Set default value of string to null
a*: {string, null: true}
Here are some of the examples that demonstrate how to define string member definition.
# String and its derived types
contactDetails : {string, address: {street: string,
city: string, state: string, default: New York},
emailId: email, websiteUrl: url}
---
# A name with default value set to anonymous
name?*: {string, anonymous, ,'[ a-z A-Z]', 5, 50}
---
~ # valid
~ N # valid
~ John # valid
In the above snippet, name
can be kept optional
and null
. When no value is passed for the name then, its default value is set to anonymous
. The name
should be a string containing characters from a to z (upper or lower case) with a minimum length of 5 and a maximum length of 50.
# Add choices for the department
department: {
type: string,
choices: [computer_science, Mechanical,
Civil, Electrical, Information_Technology]
}
Here the code snippet shows that the users can only select the department provided in choices
i.e input is restricted to the set of available departments.
# Add choices for the location
location: {
type: string,
choices: ["19.020216, 72.853729" ,
"19.242547, 73.130399" ,
"28.649840, 77.233848"]
}
In the above code snippet, users can select the location provided in choices
i.e the input is restricted to the set of available locations ( locations are enclosed in double-quotes to pass numeric data as string ).
# Add pattern that will only accept valid mobile number
mobileNumber: {string, pattern:'^(\+[0-9]{3})?[0-9]{10}$'}
---
~ "+915789654123" #valid
~ "5789654123" #valid
~ "578965412" #invalid as does not follows specified pattern
~ "915789654123" #invalid as does not follows specified pattern
# Add pattern that will only accept valid social security no.
socialSecurityno: {
string,
pattern: '^(\[0-9]{3})-\[0-9]{2}-\[0-9]{4}$'
}
---
~ "123-45-6789" #valid
~ "235-26-0012" #valid
~ "1235-12" #invalid as does not follows specified pattern
~ "123-12365" #invalid as does not follows specified pattern
~ "12345678" #invalid as does not follows specified pattern
# Set maxLen of an input string to 30
name: {string, maxLen: 30}
---
John
# Set minLen of an input string to 3
name: {string, minLen: 3}
---
Lee
# A name with minLen: 5 and maxLen: 20
name: {string, minLen: 5, maxLen: 20}
---
~ Ethan
~ Albert
~ Alexandra Daddario
~ Leonardo DiCaprio
# following input will not be accepted as minLen is 5
~ Leo
~ Alex
# following input will not be accepted as maxLen is 20
~ Venkata Narasimha Raju Vari Peta
# A name with len:9
name: {string, len: 9}
---
Elisabeth
# Set string to optional
address?: {string, optional: T}
---
# Set string to null
address*: {string, null: T}
---
# Set string to optional and null
address?*: {string, optional: T, null: T}
---
~ Mumbai India
~ New York US
~ N
~ California