Type System
This page explains how NanoJSON derives a node's type from a JavaScript value, how each type is edited and serialized, what happens to an existing value on a type switch, and the null edge cases.
Type Derivation
On import, the type is derived at runtime by getType() (src/function/getType.js):
| JS Value | getType() Returns |
|---|---|
Array.isArray(v) is true |
"array" |
typeof v === "object" (including null) |
"object" |
typeof v === "boolean" |
"boolean" |
typeof v === "number" |
"number" |
| anything else | "string" |
Per-Type Behavior
| Type | Input | Serialized As | Notes |
|---|---|---|---|
string |
textarea, multi-line |
The raw string | — |
number |
textarea, placeholder NUM |
Number(value) |
Input that can't parse as a number clears the field (except - and ., so negatives and decimals can be typed); an empty value serializes as 0 |
boolean |
true / false dropdown |
value.toLowerCase() === "true" |
An empty value is set to "true" |
object |
No value input; shows children | Object | Unlimited nesting |
array |
No value input; children shown by index with no key input |
Array | Same |
null |
— | — | Only produced by import; see "null Edge Cases" below |
Switching Types
The type dropdown (src/function/typeSelect.js:25) offers only string / number / boolean / array / object — null cannot be selected manually. On a switch, the existing value is handled per target type (typeSelect.js:30-51):
| Switch To | Effect on the Existing Value |
|---|---|
object / array |
value is cleared; if there are no children, one is added automatically (through #add, see Core Concepts) |
number |
parseFloat on the existing string; cleared if unparseable. children are not cleared, so switching back to object / array restores them |
string / boolean |
value and children are both cleared |
After a switch, updateChild() rebuilds the node's DOM and triggers Lifecycle.update, then focus moves to the value-{id} element.
null Edge Cases
getType(null) returns "object" (JavaScript's typeof null === "object"), and the two call sites handle it inconsistently:
- Object child values (
JSONEditor.js:227-234): whenvalue === null, the node's type is overridden to"null"andvalueset tonull. - Array child items (
JSONEditor.js:205-209): no equivalent handling.getType()returns"object", bute != nullis false, so it falls through to theelsebranch and is stored viaString(e)as the text"null", keeping the default"string"type.
The actual results:
| Imported Data | Result |
|---|---|
[null] |
Renders a string node containing the text "null"; serializes back as the string "null" |
{"a": null} |
While rendering that node, showValue() in valueInput() calls .replace on null (src/function/valueInput.js:56, :80) and throws a TypeError; the initial render aborts and rendered never fires |
If your data may contain null, convert it at the application layer (for example, to an empty string) before passing it to NanoJSON.
Further Reading
- How each type is assembled back into JSON: Serialization
- The
type/valuefields ofJSONEditorNode: API Reference: JSONEditorNode