Propagate runtime ID across API requests
Company: Stripe
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates proficiency in runtime ID propagation across HTTP requests, JSON parsing and serialization, nested data traversal, and type-preserving replacement in request URLs and bodies; it is categorized under Coding & Algorithms and focuses on practical application rather than purely conceptual understanding.
Constraints
- len(requests) == 5
- first_response_body contains key 'id'
- old_id is a non-empty string or integer
- Each request body is None, a JSON-like Python object, or a valid JSON string
- Total number of nested body values across all requests is at most 10000
- Headers are not modified
Examples
Input: ([{'method':'POST','url':'/widgets','headers':{'Content-Type':'application/json'},'body':{'name':'demo'}},{'method':'GET','url':'/widgets/123','headers':{},'body':None},{'method':'PATCH','url':'/widgets/123','headers':{},'body':{'id':'123','name':'updated','tags':['owner-123','123']}},{'method':'POST','url':'/widgets/123/links','headers':{},'body':'{"targetId":"123","note":"link-to-123"}'},{'method':'DELETE','url':'/widgets/123','headers':{},'body':{}}], {'id':'abc-999'}, '123')
Expected Output: [{'method':'POST','url':'/widgets','headers':{'Content-Type':'application/json'},'body':{'name':'demo'}},{'method':'GET','url':'/widgets/abc-999','headers':{},'body':None},{'method':'PATCH','url':'/widgets/abc-999','headers':{},'body':{'id':'abc-999','name':'updated','tags':['owner-abc-999','abc-999']}},{'method':'POST','url':'/widgets/abc-999/links','headers':{},'body':'{"note":"link-to-abc-999","targetId":"abc-999"}'},{'method':'DELETE','url':'/widgets/abc-999','headers':{},'body':{}}]
Explanation: Requests 2 through 5 use the runtime ID in URLs. Nested body values and substrings are also updated. The JSON string body is parsed and serialized back with sorted keys.
Input: ([{'method':'POST','url':'/orders','headers':{},'body':{'templateId':'123','keep':'request1 uses 123 but unchanged'}},{'method':'PUT','url':'/orders/123','headers':{},'body':{'parentId':'123','quantity':123,'nested':{'child':'child-123'}}},{'method':'POST','url':'/orders/123/items/123','headers':{},'body':{'items':[{'resourceId':'123'},{'resourceId':123},{'label':'order-123'}]}},{'method':'PATCH','url':'/orders/123/status','headers':{},'body':'{"id":"123","ids":["123",123],"message":"123 done"}'},{'method':'GET','url':'/orders/123/audit','headers':{},'body':None}], {'id':987}, '123')
Expected Output: [{'method':'POST','url':'/orders','headers':{},'body':{'templateId':'123','keep':'request1 uses 123 but unchanged'}},{'method':'PUT','url':'/orders/987','headers':{},'body':{'parentId':987,'quantity':987,'nested':{'child':'child-987'}}},{'method':'POST','url':'/orders/987/items/987','headers':{},'body':{'items':[{'resourceId':987},{'resourceId':987},{'label':'order-987'}]}},{'method':'PATCH','url':'/orders/987/status','headers':{},'body':'{"id":987,"ids":[987,987],"message":"987 done"}'},{'method':'GET','url':'/orders/987/audit','headers':{},'body':None}]
Explanation: The runtime ID is numeric, so exact body values like '123' and 123 become integer 987. Longer strings such as 'child-123' become 'child-987'. Request 1 is unchanged.
Input: ([{'method':'POST','url':'/resources/old','headers':{},'body':{'id':'old','note':'old in request1 stays'}},{'method':'GET','url':'/resources','headers':{},'body':None},{'method':'PUT','url':'/resources/old/old','headers':{},'body':{'emptyList':[],'emptyObj':{},'value':'no-match'}},{'method':'PATCH','url':'/resources/x','headers':{},'body':'{"items":[],"meta":{},"note":"nothing"}'},{'method':'DELETE','url':'/resources/old','headers':{},'body':{'ids':['old','prefix-old-suffix']}}], {'id':'new'}, 'old')
Expected Output: [{'method':'POST','url':'/resources/old','headers':{},'body':{'id':'old','note':'old in request1 stays'}},{'method':'GET','url':'/resources','headers':{},'body':None},{'method':'PUT','url':'/resources/new/new','headers':{},'body':{'emptyList':[],'emptyObj':{},'value':'no-match'}},{'method':'PATCH','url':'/resources/x','headers':{},'body':'{"items":[],"meta":{},"note":"nothing"}'},{'method':'DELETE','url':'/resources/new','headers':{},'body':{'ids':['new','prefix-new-suffix']}}]
Explanation: This covers empty bodies and empty nested containers. Request 1 contains the old ID but must remain unchanged. Duplicate URL occurrences are all replaced.
Input: ([{'method':'POST','url':'/things','headers':{},'body':{'id':42,'text':'42'}},{'method':'GET','url':'/things/42','headers':{},'body':None},{'method':'PATCH','url':'/things/42','headers':{},'body':{'id':42,'ref':'42','label':'thing-42','arr':[42,'42','x42x',False]}},{'method':'POST','url':'/things/42/actions','headers':{},'body':'{"number":42,"string":"42","mixed":"a42b","list":[42,"42"]}'},{'method':'DELETE','url':'/things/42','headers':{},'body':{}}], {'id':'r-007'}, 42)
Expected Output: [{'method':'POST','url':'/things','headers':{},'body':{'id':42,'text':'42'}},{'method':'GET','url':'/things/r-007','headers':{},'body':None},{'method':'PATCH','url':'/things/r-007','headers':{},'body':{'id':'r-007','ref':'r-007','label':'thing-r-007','arr':['r-007','r-007','xr-007x',False]}},{'method':'POST','url':'/things/r-007/actions','headers':{},'body':'{"list":["r-007","r-007"],"mixed":"ar-007b","number":"r-007","string":"r-007"}'},{'method':'DELETE','url':'/things/r-007','headers':{},'body':{}}]
Explanation: The old ID is numeric and the runtime ID is a string. Exact numeric and string ID values become the string runtime ID, while booleans are not treated as numbers.
Hints
- Treat each request body as a JSON tree and recursively transform dictionaries, lists, and scalar values.
- Use string replacement for URLs and longer string fragments, but replace exact JSON ID values with the runtime ID object itself to preserve its type.