JSNT
Lightweight static utility library for working with JSON data in vanilla JavaScript — read, query, transform, convert, and cache objects.
<script src="/dist/jsnt.min.js"></script>
No setup — every helper is a static method on the global jsnt object, plus the jsnt.date and jsnt.cache sub-namespaces.
const posts = {
1: { title: 'First', views: 30 },
2: { title: 'Second', views: 90 },
}
jsnt.sum(posts, 'views') // → 120
jsnt.sort(posts, 'views') // → posts ordered by views
jsnt.flatten({ a: { b: 1 } }) // → { 'a.b': 1 }
Core
Reading JSON from strings, URLs, and objects, and writing it back out.
await jsnt.parse(data) // → object | null
Resolves data to an object. A string starting with http is fetched and parsed; any other string is parsed with JSON.parse; an object is returned as-is. Returns null and logs on error.
| Param | Type | Description |
|---|---|---|
data required |
string | object | A URL, a JSON string, or an object. |
await jsnt.parse('{"a":1}') // → { a: 1 }
await jsnt.parse('https://api.site/data.json') // fetch + parse
await jsnt.parse({ a: 1 }) // → { a: 1 }
await jsnt.get(url, callback)
Fetches a JSON file and passes the parsed object to callback. Throws on a non-2xx response or a parse error.
await jsnt.get('/config.json', config => {
console.log(config.version)
})
await jsnt.download(filename, content?)
Triggers a browser download. When content is omitted, filename is fetched first and its body is saved.
jsnt.download('user.json', jsnt.toString({ id: 1 }))
jsnt.download('/remote.json') // fetch, then save under the same name
await jsnt.replace(url, key, value) // → object
Fetches a JSON file, sets one top-level key to value, and returns the updated object. Throws if any argument is missing.
const updated = await jsnt.replace('/user.json', 'active', true)
Read & write
Reach into and edit objects by key or dot-path.
jsnt.set(obj, path, value)
Sets a value at a dot-separated path, mutating obj in place. Missing intermediate objects are created automatically.
const user = {}
jsnt.set(user, 'profile.name', 'Ada')
// user → { profile: { name: 'Ada' } }
jsnt.has(obj, path) // → boolean
Returns true if the dot-separated path exists on obj.
jsnt.has({ profile: { name: 'Ada' } }, 'profile.name') // → true
jsnt.has({ profile: {} }, 'profile.age') // → false
jsnt.remove(obj, key) // → object
Deletes a top-level key and returns the object. A JSON string is parsed first.
jsnt.remove({ a: 1, b: 2 }, 'b') // → { a: 1 }
jsnt.renameKey(obj, oldKey, newKey) // → object
Returns a copy of obj with one key renamed. Returns the object unchanged if oldKey is absent.
jsnt.renameKey({ name: 'Ada' }, 'name', 'fullName') // → { fullName: 'Ada' }
Query
Inspect, filter, sort, and compare objects.
jsnt.keys(obj) // → string[]
Top-level keys of the object.
jsnt.count(obj) // → number
Number of top-level keys.
jsnt.isEmpty(obj) // → boolean
Returns true when the object has no own keys.
jsnt.filter(obj, condition) // → object
Keeps entries whose value satisfies condition(value), preserving keys.
const users = { 1: { age: 30 }, 2: { age: 12 } }
jsnt.filter(users, u => u.age >= 18) // → { 1: { age: 30 } }
jsnt.sort(obj, key) // → object
Returns a new object with entries ordered by the numeric value[key], ascending.
const posts = { a: { views: 90 }, b: { views: 30 } }
jsnt.sort(posts, 'views') // → { b: { views: 30 }, a: { views: 90 } }
jsnt.equal(a, b) // → boolean
Deep equality — recurses through objects and arrays comparing keys and values.
jsnt.equal({ a: [1, 2] }, { a: [1, 2] }) // → true
jsnt.equal({ a: 1 }, { a: 1, b: 2 }) // → false
Transform
Reshape objects and arrays.
jsnt.merge(...objects) // → object
Shallow-merges any number of objects left to right — later keys win.
jsnt.merge({ a: 1 }, { b: 2 }, { a: 3 }) // → { a: 3, b: 2 }
jsnt.flatten(obj) // → object
Flattens a nested object into a single level with dot-path keys.
jsnt.flatten({ a: { b: { c: 1 } }, d: 2 })
// → { 'a.b.c': 1, d: 2 }
jsnt.map(obj, callback) // → object | array
Recursively applies callback to every leaf value, keeping the object/array shape.
jsnt.map({ a: 1, b: { c: 2 } }, v => v * 10)
// → { a: 10, b: { c: 20 } }
jsnt.group(array, key) // → object
Groups an array of objects into buckets keyed by the value of key.
jsnt.group([{ type: 'a', n: 1 }, { type: 'b', n: 2 }, { type: 'a', n: 3 }], 'type')
// → { a: [ {…n:1}, {…n:3} ], b: [ {…n:2} ] }
jsnt.toArray(obj) // → array
The object's values as an array (Object.values).
jsnt.toArray({ a: 1, b: 2 }) // → [1, 2]
Aggregate
Reduce a keyed collection to a single number.
jsnt.sum(obj, key) // → number
Sums value[key] across all values of the object.
jsnt.sum({ 1: { views: 30 }, 2: { views: 90 } }, 'views') // → 120
jsnt.average(obj, key) // → number
Average of value[key] across all values.
jsnt.average({ 1: { views: 30 }, 2: { views: 90 } }, 'views') // → 60
Serialize
Convert between objects and JSON, YAML, and XML.
jsnt.toString(obj) // → string
JSON.stringify shorthand.
jsnt.toJson(string) // → object
JSON.parse shorthand.
jsnt.toYAML(obj) // → string
Serializes an object to YAML, indenting nested objects by two spaces.
jsnt.toYAML({ app: { name: 'Yurba', port: 80 } })
// app:
// name: Yurba
// port: 80
jsnt.parseYAML(string) // → object
Parses flat key: value YAML into an object. Blank lines and # comments are skipped.
jsnt.parseYAML('name: Yurba\nport: 80') // → { name: 'Yurba', port: '80' }
jsnt.toXML(obj) // → string
Serializes an object to an XML string wrapped in a <root> element.
jsnt.toXML({ user: { name: 'Ada' } })
// → <root><user><name>Ada</name></user></root>
jsnt.parseXML(string) // → object
Parses an XML string into a nested object. Repeated sibling tags collapse into an array.
jsnt.parseXML('<root><name>Ada</name></root>') // → { name: 'Ada' }
jsnt.validate(obj) // → boolean
Returns true if the value round-trips through JSON.stringify / JSON.parse — i.e. it is JSON-serializable.
Dates
Work with unix timestamps in seconds via the jsnt.date namespace.
jsnt.date.convert(unix, format, timeZone?) // → string
Formats a unix timestamp. Tokens: DD, MM, YYYY, hh, mm, ss.
jsnt.date.convert(1700000000, 'DD.MM.YYYY hh:mm') // → '14.11.2023 22:13'
jsnt.date.diff(a, b, unit?) // → number | object
Difference between two timestamps. With a unit (years, months, days, hours, minutes, seconds, milliseconds) returns that number; without one, returns an object of all units.
jsnt.date.diff(now, now - 3600, 'minutes') // → 60
jsnt.date.now() // → number
Current unix timestamp in seconds.
jsnt.date.add(unix, parts) // → number
Adds a duration to a timestamp. parts accepts years, months, days, hours, minutes, seconds (each defaults to 0).
jsnt.date.add(jsnt.date.now(), { days: 7, hours: 12 })
jsnt.date.substr(unix, parts) // → number
Subtracts a duration from a timestamp. Same parts shape as date.add.
jsnt.date.substr(jsnt.date.now(), { months: 1 })
Cache
A simple in-memory key–value store on the jsnt.cache namespace. Values live for the lifetime of the page.
jsnt.cache.new(key, value)
Stores (or overwrites) a value under key.
jsnt.cache.new('user', { id: 1, name: 'Ada' })
jsnt.cache.add(key, value)
Merges value into an existing entry. Works whether the stored entry is an object or a JSON string.
jsnt.cache.add('user', { role: 'admin' }) // → { id: 1, name: 'Ada', role: 'admin' }
jsnt.cache.get(key) // → any
Reads the value stored under key.
jsnt.cache.remove(key)
Deletes a single cache entry.
jsnt.cache.clear()
Empties the entire cache.