Json

class Json extends Object

Converts between JSON text and script values. Both methods are called on the class itself; a Json object is never constructed.

The class is exported by the KS module:

#Import "Ks" { Json }

Table of Contents

Encode

Returns the JSON text for a script value.

JsonText := Json.Encode(Value , Indent, NullValue)

Parameters

Value

Type: Any

The value to encode. See Type Mapping for how each type is represented.

Indent

Type: String or Integer

If omitted, an empty string or 0, the result is compact: one line, with no insignificant whitespace. This is the default.

Otherwise the result is indented by one unit per nesting level, following the same convention as JavaScript's JSON.stringify and Python's json.dumps:

The widest indent is 127 units. A string that mixes spaces and tabs, or that is neither whitespace nor a number, throws a ValueError.

Indented output separates lines with a linefeed (`n) on every platform.

NullValue

Type: Any

If omitted, only an unset value is written as JSON null. Otherwise, specify a value to write as null wherever it occurs. See Nulls.

Return Value

Type: String

Returns the JSON text.

Quotation marks are escaped, but non-ASCII characters are not: Json.Encode("äöü") returns "äöü" rather than a run of \uXXXX escapes.

The keys of a Map are written in sorted order.

Errors

A ValueError is thrown if Value contains itself, directly or through another container, or if it nests more than 128 levels deep.

Decode

Returns the script value for JSON text.

Value := Json.Decode(JsonText , CaseSense, NullValue)

Parameters

JsonText

Type: String

The JSON text to decode. Any JSON value is accepted, not only an object or array. Trailing commas and // and /* */ comments are tolerated.

CaseSense

Type: Boolean or String

The case sensitivity of every Map in the result: true (the default), false or "Locale", as for Map.CaseSense. With false, keys which differ only in case are merged into a single entry. Any other value throws a ValueError.

NullValue

Type: Any

The value a JSON null becomes. If omitted, it becomes an unset value. See Nulls.

Return Value

Type: Any

Returns the decoded value. See Type Mapping.

Errors

A ValueError is thrown if JsonText is not well-formed JSON, or if it nests more than 128 levels deep. The message describes the position of the problem.

Nulls

With no marker a JSON null decodes to an unset value, which means what unset means everywhere else: a Map key is simply absent, and an Array element is a hole.

MsgBox Json.Decode('{"a": null}').Has("a")   ; 0 — the key is not there
MsgBox Json.Decode('[1, null, 3]').Length     ; 3 — element 2 is a hole

That distinguishes a null from an empty string without any marker. To distinguish it from an absent key, supply your own marker and hand the same one back to Encode:

#Import "Ks" { Json }

NULL := Object()   ; an object, so it cannot collide with data

Config := Json.Decode('{"a": null, "b": ""}', , NULL)

MsgBox Config["a"] == NULL   ; 1
MsgBox Config["b"] == ""     ; 1

MsgBox Json.Encode(Config, , NULL)   ; {"a":null,"b":""}

Without the marker, Encode writes the marker object as an ordinary object:

MsgBox Json.Encode(Map("a", NULL))   ; {"a":{}}

Type Mapping

JSONScript valueDirection
objectMapBoth. Encoding also accepts an Object, whose own value properties become members.
arrayArrayBoth
stringStringBoth
numberInteger or FloatBoth. Decoding produces an Integer when the value is integral and fits in 64 bits, otherwise a Float.
true / falseBooleanBoth
nullunset, or your own NullValue markerBoth. See Nulls.

Dynamic properties and methods are not encoded.

Examples

Reads a value out of JSON text.

#Import "Ks" { Json }

Data := Json.Decode('{"name": "Keysharp", "tags": ["automation", "dotnet"], "stars": 42}')

MsgBox Data["name"]        ; Keysharp
MsgBox Data["tags"][1]     ; automation
MsgBox Data["stars"] + 1   ; 43, because it decoded as an Integer

Builds JSON text from a Map.

#Import "Ks" { Json }

Settings := Map("theme", "dark", "size", 14, "recent", ["a.ks", "b.ks"])
MsgBox Json.Encode(Settings)   ; {"recent":["a.ks","b.ks"],"size":14,"theme":"dark"}

Writes a file a person will edit, indented with two spaces.

#Import "Ks" { Json }

Settings := Map("theme", "dark", "wrap", true)
FileOpen(A_ScriptDir "\settings.json", "w").Write(Json.Encode(Settings, 2))

; {
;   "theme": "dark",
;   "wrap": true
; }

Reads a configuration file whose key spellings cannot be relied on, and tells a missing setting apart from one that was explicitly set to null.

#Import "Ks" { Json }

NULL := Object()

Config := Json.Decode(FileRead("config.json"), CaseSense: false, NullValue: NULL)

MsgBox Config["timeout"]   ; found whether the file spelled it Timeout, TIMEOUT or timeout

if !Config.Has("proxy")
    MsgBox "no proxy setting"
else if (Config["proxy"] == NULL)
    MsgBox "proxy explicitly disabled"
else
    MsgBox "proxy: " Config["proxy"]

Boolean, Map, Array, FileRead, KS module