JSON, derived from JavaScript object literal notation:
JSON is a format based on JavaScript object literal syntax. When utilizing the JSON.parse()
method to convert a JSON string into a JavaScript value, you essentially get objects resembling JavaScript object literals:
let foo = { "a": 1, "b": "two", "c": false };
console.log(foo) // { "a": 1, "b": "two", "c": false }
let bar = JSON.parse('{ "a": 1, "b": "two", "c": false }');
console.log(bar) // { "a": 1, "b": "two", "c": false }
In JavaScript, objects consist of key-value pairs where the keys are primarily strings and the values can be of any type. These keys do not require prior declaration in JavaScript's perspective. All JavaScript objects are inherently "expando" objects.
You access an object's property either through dot notation (if the key name is a valid identifier):
foo.a;
or bracket notation (typically used when the key name isn't a valid identifier or arises from an expression result):
foo["a"];
const k = "a";
foo[k];
For accessing properties on such objects, avoid using get()
. Instead, there exists a JS Map
class which facilitates storing key-value pairs with a get()
method for retrieval. Nevertheless, it's vital to note that a Map
differs from a basic JS object. While there are use cases for Map
s, handling deserialized JSON is typically not one of them.
Hence, your runtime code might resemble this:
let json = JSON.parse(
'{"id":"abc123","name":"name name","siteContent":{"random1":"hi","random2":"hey"}}'
);
console.log(json.siteContent.random1); // hi
TypeScript adds a static typing system to describe JavaScript functionality without altering its behavior. An interface
type like SiteContent
serves as a way to define the structure of specific JavaScript objects expected at runtime.
In TypeScript, object types may possess known properties with defined string literal keys such as id
or name
. Moreover, employing JavaScript objects as expando objects where keys have predetermined value types but unknown beforehand is common. Hence, TypeScript enables assigning an object type with an index signature. The object type {[k: string]: number}
signifies "you can index into this object with any key k
of type string
, and if there's a property, it shall be of type number
. For instance, you desire the siteContent
property to be an object type featuring arbitrary keys but containing string
values:
interface SiteContent {
id: string;
name: string;
siteContent: { [k: string]: string }
}
With that specified index signature, your TypeScript code will compile error-free:
let json = JSON.parse(
'{"id":"abc123","name":"name name","siteContent":{"random1":"hi","random2":"hey"}}'
) as SiteContent;
console.log(json.siteContent.random1); // hi
Playground link to code