Coding questions · OpenAI
Implement in-memory KV store with serialization
This question evaluates skills in designing and implementing an in-memory key-value store with serialization, testing data structure design, API design (set/get/serialize/deserialize), serialization format selection, type fidelity for common Python types, and robust error handling.
Implement an in-memory key-value store in Python that supports setting and retrieving values and can serialize and deserialize the entire store. Define a clear API (e.g., set(key, value), get(key), serialize(), deserialize(blob)). Choose a serialization format (e.g., JSON or pickle), explain your choice, and ensure type fidelity for common Python types (ints, floats, strings, lists, dicts). Handle missing keys and malformed or incompatible serialized input gracefully. Provide basic tests to demonstrate that data round-trips correctly.
Implement In-Memory KV Store with Serialization
Implement a function solution(operations) that simulates a small in-memory key-value store with a typed, JSON-backed serialization API.
The store supports four operations: set, get, serialize, and deserialize. JSON is used as the serialization format because it is human-readable, portable, and safer than pickle. To preserve type fidelity across a serialize/deserialize round-trip, the store only accepts values built from a restricted set of types.
What to implement
operations is a list of operations to apply in order, starting from an empty store. Each operation is a sequence (e.g. a tuple) whose first element is the command name and whose remaining elements are that command's arguments.
Return a list with exactly one result per operation, in the same order.
Supported values
A value is supported if it is one of the following (checked recursively):
- an
int - a finite
float(i.e. notNaN,inf, or-inf) - a
str - a
listwhose every element is supported - a
dictwhose every key is astrand whose every value is supported
bool and None are not supported values (note that in Python True/False are int instances, so they must be rejected explicitly).
Operations
('set', key, value)
- If
keyis astrandvalueis supported, store the value underkey(overwriting any existing entry) and appendTrue. - Otherwise append
Falseand leave the store unchanged.
('get', key)
- Append the value currently stored under
key, orNoneif the key is not present.
('serialize',)
- Append a compact JSON string of the entire store, with keys sorted lexicographically and no extra whitespace (use
,and:as separators). Non-finite floats are never produced. The serialization of an empty store is"{}".
('deserialize', blob)
blobmust be astrcontaining JSON that parses to an object representing the whole store.- If
blobis a string, parses successfully as JSON, the parsed result is adict, and that dict is supported, then replace the entire store with it and appendTrue. - Otherwise (non-string
blob, malformed JSON, a parsed value that is not adict, or a dict containing unsupported values) appendFalseand leave the store unchanged.
Edge cases
- Any operation whose command is unrecognized, whose argument count is wrong, or that is empty appends
False— except agetwith the wrong argument count, which appendsNone. - An empty
operationslist returns an empty list.
Constraints
0 <= len(operations) <= 10^4- Store keys and all nested dict keys must be strings.
- Supported stored values are
int, finitefloat,str,list, anddict, with recursive nesting allowed. - The total size of all values and serialized blobs processed is at most
2 * 10^5.
Example
operations = [
('set', 'count', 5),
('set', 'info', {'name': 'Ada', 'scores': [1, 2.5]}),
('serialize',),
('deserialize', '{"count":5,"info":{"name":"Ada","scores":[1,2.5]}}'),
('get', 'info'),
]
# returns:
# [True,
# True,
# '{"count":5,"info":{"name":"Ada","scores":[1,2.5]}}',
# True,
# {'name': 'Ada', 'scores': [1, 2.5]}]
Hints
- Use a normal dictionary for the live store, and write one recursive helper that validates whether a value can be safely serialized without losing type information.
- Make serialization deterministic by sorting keys and removing extra whitespace, so exact string comparisons in tests are stable.
Approach
The solution simulates a typed key-value store by interpreting a list of operations, appending one result per operation.
Core data structure. A plain Python dict named store holds the data. The whole solution hinges on one validation helper:
is_supported(value) recursively checks that a value is one of the allowed types. The ordering matters:
boolandNoneare rejected first (noteTrue/Falseareintsubclasses in Python, so they must be excluded before theintcheck).intandstrare always accepted.floatis accepted only whenmath.isfinite(blocksNaN/inf, which JSON can't round-trip safely).listrecurses into every element;dictrequires every key to be astrand every value to passis_supported.
Operation dispatch. For each op, the first element is the command. Each branch also length-checks the tuple defensively:
set-> requires astrkey and a supported value; stores and returnsTrue, elseFalse(store unchanged).get-> returnsstore.get(key), yieldingNonefor a missing key.serialize->json.dumps(store, sort_keys=True, separators=(',',':'), allow_nan=False)produces a compact, key-sorted, deterministic blob.deserialize-> rejects non-strings,try/exceptguards malformed JSON, then accepts only when the parsed result is adictthat passesis_supported. On success it replacesstorewholesale; otherwise leaves it untouched.
Why it's correct. Validation is enforced on both ingress paths (set and deserialize), so the store always holds only round-trippable values. Malformed input is caught by try/except and the dict-type check, guaranteeing the "store unchanged on failure" contract.
- Time complexity: O(S), where S is the total size (element/character count) of all values and JSON blobs processed across operations. Each
is_supportedvalidation,json.dumps, andjson.loadstouches each element/character a constant number of times. - Space complexity: O(S) — the store plus any parsed JSON object hold up to S elements, and
is_supportedrecursion depth is bounded by the nesting depth of the value (at most O(S)).