JavaScript · Syntax · Intermediate
JSON and Date
Serializing and deserializing data with JSON, and working with the Date object.
Quick topic start and explanations before exercises (exercises below):
The Date object: creation, UTC methods, and timezone pitfalls
#replacer, reviver, toJSON(), and structuredClone vs JSON roundtrip
#Exercises:
Parse a JSON string and return the parsed JavaScript object.
function parseJson(str) {
// your code here
}
const result = parseJson('{"name": "Alice", "age": 30}');
console.log(result.name); // 'Alice'
console.log(result.age); // 30
Solution
function parseJson(str) {
return JSON.parse(str);
}
Serialize a JavaScript object to a JSON string with 2-space indentation.
function toJson(obj) {
// your code here
}
const result = toJson({ name: 'Alice', scores: [88, 92] });
console.log(result);
// {
// "name": "Alice",
// "scores": [
// 88,
// 92
// ]
// }
Solution
function toJson(obj) {
return JSON.stringify(obj, null, 2);
}
Create a `Date` object from the ISO string '2024-03-15T14:30:00Z' and return its UTC year, month (1-indexed), and day as an object.
function parseIsoDate(isoStr) {
// Return { year, month, day } in UTC
}
const result = parseIsoDate('2024-03-15T14:30:00Z');
console.log(result.year); // 2024
console.log(result.month); // 3
console.log(result.day); // 15
Solution
function parseIsoDate(isoStr) {
const d = new Date(isoStr);
return {
year: d.getUTCFullYear(),
month: d.getUTCMonth() + 1,
day: d.getUTCDate(),
};
}
Return the number of days between two ISO date strings (always positive).
function daysBetween(iso1, iso2) {
// your code here
}
console.log(daysBetween('2024-01-01', '2024-03-15')); // 74
console.log(daysBetween('2024-03-15', '2024-01-01')); // 74
Solution
function daysBetween(iso1, iso2) {
const MS_PER_DAY = 1000 * 60 * 60 * 24;
return Math.round(Math.abs(new Date(iso2) - new Date(iso1)) / MS_PER_DAY);
}
Use a replacer function in `JSON.stringify` to exclude any keys whose values are `null` or `undefined`.
function stringifyClean(obj) {
// your code here
}
const obj = { name: 'Alice', age: null, score: 88, notes: undefined };
console.log(stringifyClean(obj));
// '{"name":"Alice","score":88}'
Solution
function stringifyClean(obj) {
return JSON.stringify(obj, (key, value) => {
if (value === null || value === undefined) return undefined;
return value;
});
}
Use a reviver function in `JSON.parse` to convert any string values that look like ISO dates (YYYY-MM-DD) into `Date` objects.
function parseWithDates(str) {
// your code here
}
const result = parseWithDates('{"name":"Alice","birthday":"1990-05-21","score":42}');
console.log(result.birthday instanceof Date); // true
console.log(result.birthday.getUTCFullYear()); // 1990
console.log(result.score); // 42 (number, unchanged)
Solution
function parseWithDates(str) {
return JSON.parse(str, (key, value) => {
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value)) {
return new Date(value);
}
return value;
});
}
Format a Date object as 'YYYY-MM-DD' (ISO date string, UTC).
function formatDate(date) {
// your code here
}
console.log(formatDate(new Date('2024-03-15T14:30:00Z'))); // '2024-03-15'
console.log(formatDate(new Date('2024-12-01T00:00:00Z'))); // '2024-12-01'
Solution
function formatDate(date) {
return date.toISOString().slice(0, 10);
}
Given a JSON array of event objects with 'date' fields (ISO strings), return the event with the most recent date.
function latestEvent(jsonStr) {
// your code here
}
const events = '[{"name":"Conf","date":"2024-09-12"},{"name":"Workshop","date":"2024-11-03"},{"name":"Meetup","date":"2024-07-20"}]';
console.log(latestEvent(events).name); // 'Workshop'
Solution
function latestEvent(jsonStr) {
const events = JSON.parse(jsonStr);
return events.reduce((latest, e) => e.date > latest.date ? e : latest);
}
Deep clone a JavaScript object using JSON serialization (without using structuredClone).
function deepClone(obj) {
// your code here
}
const original = { name: 'Alice', scores: [88, 92], meta: { active: true } };
const clone = deepClone(original);
clone.scores.push(100);
clone.meta.active = false;
console.log(original.scores.length); // 2 (not affected)
console.log(original.meta.active); // true (not affected)
Solution
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
Given an array of objects with a `toJSON()` method, demonstrate custom JSON serialization: each object should serialize as `{ type, value }` where type is the class name.
class Temperature {
constructor(celsius) { this.celsius = celsius; }
toJSON() {
// your code here — return the object to serialize
}
}
const temps = [new Temperature(100), new Temperature(0), new Temperature(37)];
const json = JSON.stringify(temps);
console.log(json);
// '[{"type":"Temperature","value":100},{"type":"Temperature","value":0},{"type":"Temperature","value":37}]'
Solution
class Temperature {
constructor(celsius) { this.celsius = celsius; }
toJSON() {
return { type: this.constructor.name, value: this.celsius };
}
}