← All tasks Task 11 of 12 unsolved

11. JSON Deep Masking

Recursion Immutability ~30 min

Mask values inside a nested JSON-like map by dot-notation paths (user.email, profile.address.zip). Non-existent paths are silently skipped; non-string leaves are left alone; the original map must not be mutated — return a fresh structure.

This is the masker for JSONB / JSON column types in Synthesized.io — masking happens before serialization back to disk.

Tests this task must pass

  1. Simple nested pathuser.email is masked; sibling fields (user.name, user.age) are untouched.
  2. Non-existent path is a no-opuser.phone when there is no phone returns the input unchanged (deep equality preserved).
  3. Multiple paths in one calluser.email and user.name can be masked together; non-listed siblings stay intact.
  4. Top-level pathnotes at the root level is masked.
  5. No mutation — the original input map (and its nested maps) is unchanged after the call.
//sampleStart fun maskJsonPaths(json: Map<String, Any?>, paths: List<String>, masker: (String) -> String): Map<String, Any?> { // Mask values at specified dot-notation paths in a nested map. // "user.email" → navigate to json["user"]["email"], apply masker // Non-existent paths → ignore, return json unchanged // Only mask String values. Leave numbers/booleans untouched. // Return a NEW map (don't mutate input). TODO() } //sampleEnd fun main() { val masker: (String) -> String = { "***" } val json = mapOf( "user" to mapOf("email" to "alex@test.com", "age" to 30, "name" to "Alex"), "notes" to "some notes", "count" to 42 ) // Test 1: Simple path val r1 = maskJsonPaths(json, listOf("user.email"), masker) val user1 = r1["user"] as Map<*, *> check(user1["email"] == "***") { "FAIL: email should be masked. Got: ${user1["email"]}" } check(user1["name"] == "Alex") { "FAIL: name untouched" } check(user1["age"] == 30) { "FAIL: age untouched" } println("✅ Test 1: user.email masked") // Test 2: Non-existent path — no error val r2 = maskJsonPaths(json, listOf("user.phone"), masker) check(r2 == json) { "FAIL: non-existent path should return unchanged" } println("✅ Test 2: Non-existent path ignored") // Test 3: Multiple paths val r3 = maskJsonPaths(json, listOf("user.email", "user.name"), masker) val user3 = r3["user"] as Map<*, *> check(user3["email"] == "***" && user3["name"] == "***") { "FAIL: both masked" } check(user3["age"] == 30) { "FAIL: age untouched" } println("✅ Test 3: Multiple paths masked") // Test 4: Top-level path val r4 = maskJsonPaths(json, listOf("notes"), masker) check(r4["notes"] == "***") { "FAIL: top-level masked" } check(r4["count"] == 42) { "FAIL: count untouched" } println("✅ Test 4: Top-level path") // Test 5: Don't mutate original check((json["user"] as Map<*,*>)["email"] == "alex@test.com") { "FAIL: original mutated!" } println("✅ Test 5: Original not mutated") println("\n🎉 ALL TESTS PASSED!") }
← Previous Next: Dialect Type Mapping →