WEB / WEB-17.S03
Deserialization and object reconstruction boundaries
Separate parsing, schemas, permission and trusted constructors.
1. Core · Mechanism
Read every scenario without motion
DTO allowed
- Fixed JSON ready
The application has prepared book-note/v1 text: id=note-A, title=Tea & Bread, pageCount=12 integer. Parser and constructor work locally in one process; external data selects no behavior.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer
- DTO / constructor
- Local parser waiting; no object constructed
- Plain values parsed
JSON.parse locally produces plain values; text selects no method or runtime class and no reviver is used.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer
- DTO / constructor
- Parsed plain object; Book instance=false
- Schema decision
id, title and pageCount are exactly the three approved keys. id=note-A, title length=11 and integer pageCount=12 pass; schema acceptance is not yet a readAllowed decision.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer
- DTO / constructor
- Schema valid; context pending
- Context decision
contextPresent=true and readAllowed=true are application inputs independent of the JSON. After they pass, the three-field DTO may enter the fixed Book constructor; input selects no class or method.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer
- DTO / constructor
- Schema and context accepted; projection pending
- Explicit projection
After schema and read context pass, the application explicitly copies only id/title/pageCount into its fixed Book constructor. A Book instance now exists; its caption has not yet been produced.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer
- DTO / constructor
- Fixed Book constructed; plain caption pending
- Local result ready
The caption is only a plain string; DOM/store/network delivery and object mutation are not part of this scene.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer
- DTO / constructor
- Caption ready: Tea & Bread (12 pages); mutation=false
Unknown field
- Fixed JSON ready
The application has prepared book-note/v1 text: id=note-A, title=Tea & Bread, pageCount=12 integer; subtitle=Reading notes. Parser and constructor work locally in one process; external data selects no behavior.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer; subtitle=Reading notes
- DTO / constructor
- Local parser waiting; no object constructed
- Plain values parsed
JSON.parse locally produces plain values; text selects no method or runtime class and no reviver is used.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer; subtitle=Reading notes
- DTO / constructor
- Parsed plain object; Book instance=false
- Schema decision
subtitle=Reading notes is valid JSON data outside the approved id/title/pageCount keys. unknownFieldMode=reject denies the DTO; context evaluation and construction do not run.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer; subtitle=Reading notes
- DTO / constructor
- Schema denied; constructor not run
- Schema denial retained
Schema rejection stops the context gate from running. This branch makes no new actor-permission decision and performs no reconstruction.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer; subtitle=Reading notes
- DTO / constructor
- Schema denied; context not evaluated
- Explicit projection
This denied branch performs no explicit DTO projection or Book-constructor call. Constructor count=0 means no domain object or caption; an object from the normal branch cannot be reused here.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer; subtitle=Reading notes
- DTO / constructor
- Constructor count=0; protected body absent
- Local result ready
The caption is only a plain string; DOM/store/network delivery and object mutation are not part of this scene.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer; subtitle=Reading notes
- DTO / constructor
- No caption/body/delivery; mutation=false
Type mismatch
- Fixed JSON ready
The application has prepared book-note/v1 text: id=note-A, title=Tea & Bread, pageCount="12" string. Parser and constructor work locally in one process; external data selects no behavior.
- Fixed JSON data
- note-A / Tea & Bread / "12" string
- DTO / constructor
- Local parser waiting; no object constructed
- Plain values parsed
JSON.parse locally produces plain values; text selects no method or runtime class and no reviver is used.
- Fixed JSON data
- note-A / Tea & Bread / "12" string
- DTO / constructor
- Parsed plain object; Book instance=false
- Schema decision
pageCount="12" is a JSON string. This contract requires an integer from 1–1000 with no coercion; the type gate denies it. Successful parsing does not run context evaluation or construction.
- Fixed JSON data
- note-A / Tea & Bread / "12" string
- DTO / constructor
- Schema denied; constructor not run
- Schema denial retained
Schema rejection stops the context gate from running. This branch makes no new actor-permission decision and performs no reconstruction.
- Fixed JSON data
- note-A / Tea & Bread / "12" string
- DTO / constructor
- Schema denied; context not evaluated
- Explicit projection
This denied branch performs no explicit DTO projection or Book-constructor call. Constructor count=0 means no domain object or caption; an object from the normal branch cannot be reused here.
- Fixed JSON data
- note-A / Tea & Bread / "12" string
- DTO / constructor
- Constructor count=0; protected body absent
- Local result ready
The caption is only a plain string; DOM/store/network delivery and object mutation are not part of this scene.
- Fixed JSON data
- note-A / Tea & Bread / "12" string
- DTO / constructor
- No caption/body/delivery; mutation=false
Context missing
- Fixed JSON ready
The application has prepared book-note/v1 text: id=note-A, title=Tea & Bread, pageCount=12 integer. Parser and constructor work locally in one process; external data selects no behavior.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer
- DTO / constructor
- Local parser waiting; no object constructed
- Plain values parsed
JSON.parse locally produces plain values; text selects no method or runtime class and no reviver is used.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer
- DTO / constructor
- Parsed plain object; Book instance=false
- Schema decision
id, title and pageCount are exactly the three approved keys. id=note-A, title length=11 and integer pageCount=12 pass; schema acceptance is not yet a readAllowed decision.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer
- DTO / constructor
- Schema valid; context pending
- Context decision
The normal JSON shape passes, but contextPresent=false and readAllowed=null. Permission remains unknown; safe denial withholds construction/projection rather than establishing false permission.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer
- DTO / constructor
- No context; permission UNKNOWN; no constructor
- Explicit projection
This denied branch performs no explicit DTO projection or Book-constructor call. Constructor count=0 means no domain object or caption; an object from the normal branch cannot be reused here.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer
- DTO / constructor
- Constructor count=0; protected body absent
- Local result ready
The caption is only a plain string; DOM/store/network delivery and object mutation are not part of this scene.
- Fixed JSON data
- note-A / Tea & Bread / 12 integer
- DTO / constructor
- No caption/body/delivery; mutation=false
ACTORS · STATE · DATA FLOW
JSON produces data, not a choice of behavior
Deserialization turns an external representation into values that a program can read. For JSON these are objects, arrays, strings, numbers, booleans and null. A book object returned by JSON.parse is not an instance of the application’s Book class; its text does not automatically choose a caption method or approved constructor. Reconstruction is a separate design decision: the application chooses which validated fields enter a trusted domain type. Atlas Notes uses book-note/v1 with id, title and pageCount. Tea & Bread is only a plain title string. Successful parsing proves neither that pageCount is an appropriate integer, that the ID refers to the requested object, nor that an actor may use that data. This lesson creates only a fixed read-only caption; it derives no DOM, file or database action from the object.
From a closed DTO to a trusted constructor
The selected profile accepts exactly three keys: pageCount is an integer from 1 to 1000, title is a string from 1 to 80 characters, and id must equal note-A. An unknown subtitle field is rejected in this profile; this is not a claim that every API must reject all unknown fields. A versioned contract can choose another compatibility policy, but silent field loss should be visible. An accepted DTO is built by explicit projection, and the constructor receives only those three values. Its name is not read from the input; external data selects no runtime module or method. ContextPresent and readAllowed are separate server-side inputs; no JSON field can open that gate. With missing context, even a correctly shaped object is not reconstructed for client delivery. Validation and authorization each retain their own decision.
Revivers and format boundaries
The optional JSON.parse reviver is a function supplied by the application, not an executable instruction inside the text. A transformation hook introduces behavior that needs its own review; this profile uses no reviver. JSON is also not a universal, lossless snapshot of every runtime value. Class identity, methods and special runtime behavior are outside this three-field DTO. Numeric precision, nesting and text-size limits belong in the parser and contract profile. Unique object member names matter for interoperability; choose an explicit ingress parser policy rather than depending on duplicate-key behavior. This fixture produces no duplicate keys and runs no duplicate-preserving parser. A pure data format narrows the surface, but does not independently guarantee safe downstream business methods, output interpretation or permission.
2. Red · Trust & Impact
Read every scenario without motion
Unknown field
- The data-only profile was selected
book-note/v1 accepts only id, title and pageCount. The unknown-field row adds subtitle=Reading notes, which conflicts with this closed contract.
- External JSON data
- Closed keys: 3
- Closed DTO gate
- Shape review pending
- Constructor/caption boundary
- Constructor not called
- JSON parsing and domain type were separated
The JSON parser can read subtitle as ordinary data. Parsing does not allow the field into the approved DTO or behavior selection.
- External JSON data
- Parsed values only
- Closed DTO gate
- Unknown field present
- Constructor/caption boundary
- Domain object absent
- The closed-DTO gate rejected the data
unknownFieldMode=reject withholds an accepted projection. Silently deleting the field would change this profile’s denial into acceptance.
- External JSON data
- Shape mismatch known
- Closed DTO gate
- Projection withheld
- Constructor/caption boundary
- Constructed=false
- The constructor boundary remained closed
expectedConstructed=false. An input format name or title cannot select the fixed application Book constructor; only approved application code invokes it.
- External JSON data
- No approved DTO
- Closed DTO gate
- No constructor call
- Constructor/caption boundary
- No caption produced
- No plain caption was delivered
expectedDelivery=false, expectedBody=null and expectedMutation=false remain. Parsed data alone is insufficient to advance to the caption consumer.
- External JSON data
- Delivery=false
- Closed DTO gate
- Body=null
- Constructor/caption boundary
- Mutation=false
- The failure class remained precise
This row is contract rejection of an ordinary unknown field, not evidence of object injection or a dangerous loader. The data-only boundary deliberately avoids loading behavior.
- External JSON data
- Known contract rejection
- Closed DTO gate
- Permission separate
- Constructor/caption boundary
- No behavior loading
Type mismatch
- The data-only profile was selected
book-note/v1 requires pageCount as an integer in 1..1000. The wrong-type row contains pageCount="12"; a numeric-looking string remains a string.
- External JSON data
- Closed keys: 3
- Closed DTO gate
- Shape review pending
- Constructor/caption boundary
- Constructor not called
- JSON parsing and domain type were separated
The parser correctly produces pageCount as a string. This is not a syntax error; mismatch with the application’s integer contract occurs at a separate stage.
- External JSON data
- Parsed values only
- Closed DTO gate
- pageCount type: string
- Constructor/caption boundary
- Domain object absent
- The closed-DTO gate rejected the data
Failure of the integer-type gate withholds explicit projection. Automatically converting the string into a number is not this contract’s declared behavior.
- External JSON data
- Shape mismatch known
- Closed DTO gate
- Projection withheld
- Constructor/caption boundary
- Constructed=false
- The constructor boundary remained closed
expectedConstructed=false. An input format name or title cannot select the fixed application Book constructor; only approved application code invokes it.
- External JSON data
- No approved DTO
- Closed DTO gate
- No constructor call
- Constructor/caption boundary
- No caption produced
- No plain caption was delivered
expectedDelivery=false, expectedBody=null and expectedMutation=false remain. Parsed data alone is insufficient to advance to the caption consumer.
- External JSON data
- Delivery=false
- Closed DTO gate
- Body=null
- Constructor/caption boundary
- Mutation=false
- The failure class remained precise
This row is an ordinary type mismatch, not unreadable numeric syntax or false actor permission. Format and permission causes remain separate.
- External JSON data
- Known contract rejection
- Closed DTO gate
- Permission separate
- Constructor/caption boundary
- No behavior loading
ASSUMPTION · BOUNDARY · CONTROL
The assumption between data and runtime type
The failure class under review gives an external representation too much influence over runtime type or behavior selection. A parseable object is not sufficient evidence of a trusted domain object. The risk requires the application to connect external values to behavior-bearing objects, side effects or permission decisions without an approved DTO boundary. This example contains no class-selecting payload or dangerous loader; the finite Book constructor is fixed application code. The unknown subtitle branch demonstrates a contract mismatch, not an exploit result. Keep the states “parsed”, “shape valid”, “actor permitted” and “domain object constructed” separate. Asking where external data stops being a field projection and starts selecting behavior is a concrete review boundary. In this profile that transition occurs only through an approved constructor.
Signatures, schemas and context provide different evidence
If integrity verification exists, it contributes evidence that particular bytes came with appropriate provenance; it does not independently authorize the business meaning of their fields or the recipient’s action. No actual signature exists in this lesson, and provenance is an external dependency rather than an assumed result. In the wrong-type branch pageCount arrives as a string. The parser correctly creates a string, while the contract expects an integer and denies it. The missing-context branch uses the same normal DTO but lacks context evidence; it does not prove that the actor is unauthorized. The safe result still withholds reconstruction delivery and its body. Distinguishing format mismatch, missing permission evidence and unsafe runtime reconstruction reduces both misplaced confidence and unnecessary alarms. The fixed example is applied to no organizational format or actual endpoint.
3. Blue · Secure development & defense
Read every scenario without motion
Field projection
- Normal JSON data was read
The normal text contains id=note-A, title=Tea & Bread and pageCount=12. JSON.parse produces a data object; the text supplies neither a Book prototype nor method implementation.
- JSON/context observation
- Parsed: 3 data fields
- Projection review
- Book instance=false
- Construction conclusion
- Reconstruction pending
- Typed-DTO conditions were checked
Approved keys and types are compared with the profile. Title length 1..80 and pageCount 1..1000 must pass before creating an object with behavior.
- JSON/context observation
- Closed shape accepted
- Projection review
- Title/count within bounds
- Construction conclusion
- Constructor pending
- Authorization context was read separately
The normal row declares contextPresent=true and readAllowed=true. DTO validity cannot replace these permission values; they are supplied separately.
- JSON/context observation
- Shape accepted
- Projection review
- Read allowed=true
- Construction conclusion
- Projection eligible
- Three fields were explicitly copied
The pipeline copies only id, title and pageCount into an application projection. approvedConstructor=fixed application Book does not select classes or methods from input.
- JSON/context observation
- Explicit 3-field projection
- Projection review
- Constructor fixed by app
- Construction conclusion
- Constructed=true
- The caption remained a plain string
expectedBody contains caption=Tea & Bread (12 pages). This string does not establish HTML parsing or DOM rendering; expectedMutation=false.
- JSON/context observation
- Caption: Tea & Bread (12 pages)
- Projection review
- Plain string
- Construction conclusion
- Mutation=false
- Freeze and authority were separated
runtimeLedger declares freezeIsAuthorization=false. Constraining local object mutation proves neither identity, resource permission nor immutability of an entire nested graph.
- JSON/context observation
- Reconstruction known
- Projection review
- Freeze ≠ permission
- Construction conclusion
- DOM/persistence unobserved
Context absent
- The same DTO was selected with missing context
The context-missing row carries the normal three-field JSON text. contextPresent=false and readAllowed=null are evidence conditions distinct from format mismatch.
- JSON/context observation
- Normal DTO data
- Projection review
- Context present=false
- Construction conclusion
- Read allowed=null
- Format validity did not become permission
Even with correct id, title and pageCount, approved actor context is missing. Guessing identity from field values cannot repair that missing evidence.
- JSON/context observation
- Shape valid
- Projection review
- Permission UNKNOWN
- Construction conclusion
- No guessed context
- Withheld reconstruction was matched
expectedConstructed=false remains. Because constructor admission needs context as well as shape, a parsed plain object is insufficient.
- JSON/context observation
- Parsed data known
- Projection review
- Constructor not called
- Construction conclusion
- No domain caption
- The negative consumer outcome was checked
expectedDelivery=false, expectedBody=null and expectedMutation=false are retained together. Review does not infer absent construction from an error label alone.
- JSON/context observation
- Delivery=false
- Projection review
- Body=null
- Construction conclusion
- Mutation=false
- Unknown permission was separated from denial cause
The safe outcome is withheld delivery without claiming verified false actor permission. The normal row’s true value is not copied here without finding the context source.
- JSON/context observation
- Safe delivery withheld
- Projection review
- Permission remains UNKNOWN
- Construction conclusion
- Context evidence required
- Data-reconstruction scope was preserved
This finite pipeline relates plain JSON to a fixed constructor. Endpoint authentication, rich deserializers and persistence safety require separate implementation evidence.
- JSON/context observation
- Data-only boundary known
- Projection review
- Identity unobserved
- Construction conclusion
- No broad deserializer claim
IMPLEMENTATION · SECURITY CONTROL · VERIFICATION
Explicit projection and bounded reconstruction
The defensive pipeline is external text → JSON values → closed schema → authorization context → explicit DTO → fixed constructor → plain caption. Construction does not run before schema acceptance, and no caption is delivered without context. The success branch copies only id, title and pageCount. Freezing the object is a local choice that reduces mutation risk; it neither authenticates identity nor makes every nested graph automatically immutable. The method implementation is fixed application code, so input need not load behavior. Adding a field later requires a joint review of contract version, compatibility and constructor projection. Other formats requiring richer runtime serialization need separate parser, type-allowlist and behavior review. Pure JSON gives this small example a clear boundary; it does not certify every format or deserializer as secure.
Prove that reconstruction did not occur
The fixture checks more than whether a successful caption is correct. For unknown field, wrong type and missing context it requires constructed=false, delivered=false, body=null and mutation=false together. The native check uses fixed JSON.parse data to observe that a plain object is not a Book instance, that an approved constructor runs after validated projection, and that the caption is only a plain string. These are actual JSON and class observations; they establish neither a web endpoint’s authorization nor the safety of an unsafe serialization format. Parsing a denied row must not increment the constructor counter. Missing context remains unknownPermission, with a diagnostic selected by the application profile. The checks retain value as contracts change because they compare field, type and context boundaries alongside the normal input. Browser DOM, persistence and remote deserialization services remain outside the evidence.
NOW APPLY IT TO THE CASE
When can parsed JSON become an approved domain object?
book-note/v1 requires a closed DTO and current context. Input does not select behavior; three fields pass through application projection to a fixed Book constructor.
Separate decisions for verified actor, tenant relation and requested action in the case. Do not substitute authentication or proof success for object permission.
Open the related case file ↗READ THE EXAMPLE TOGETHER
Atlas Notes — decision ledger
Select a field and examine what it supports and where the evidence ends.
Read the raw artifact and field explanations
{
"profile": {
"format": "book-note/v1",
"keys": [
"id",
"title",
"pageCount"
],
"id": "note-A",
"titleLength": [
1,
80
],
"pageCountRange": [
1,
1000
],
"unknownFieldMode": "reject",
"approvedConstructor": "fixed application Book",
"reviverUsed": false,
"actualEndpoint": false
},
"rows": [
{
"case": "normal",
"text": "{\"id\":\"note-A\",\"title\":\"Tea & Bread\",\"pageCount\":12}",
"contextPresent": true,
"readAllowed": true,
"expectedConstructed": true,
"expectedDelivery": true,
"expectedBody": {
"caption": "Tea & Bread (12 pages)"
},
"expectedMutation": false
},
{
"case": "unknown-field",
"text": "{\"id\":\"note-A\",\"title\":\"Tea & Bread\",\"pageCount\":12,\"subtitle\":\"Reading notes\"}",
"contextPresent": true,
"readAllowed": true,
"expectedConstructed": false,
"expectedDelivery": false,
"expectedBody": null,
"expectedMutation": false
},
{
"case": "wrong-type",
"text": "{\"id\":\"note-A\",\"title\":\"Tea & Bread\",\"pageCount\":\"12\"}",
"contextPresent": true,
"readAllowed": true,
"expectedConstructed": false,
"expectedDelivery": false,
"expectedBody": null,
"expectedMutation": false
},
{
"case": "context-missing",
"text": "{\"id\":\"note-A\",\"title\":\"Tea & Bread\",\"pageCount\":12}",
"contextPresent": false,
"readAllowed": null,
"expectedConstructed": false,
"expectedDelivery": false,
"expectedBody": null,
"expectedMutation": false
}
],
"pipeline": [
"JSON values",
"closed typed DTO",
"current authorization context",
"explicit three-field projection",
"trusted fixed Book constructor",
"plain caption"
],
"runtimeLedger": {
"parsedJSONHasBookPrototype": false,
"textSelectsConstructor": false,
"methodLoadedFromText": false,
"freezeIsAuthorization": false,
"duplicateKeyParserExecuted": false
},
"boundaries": {
"actualUnsafeDeserializer": false,
"actualDOM": false,
"actualPersistence": false,
"actualIdentity": false
}
}- profile
- Local closed contract and trusted constructor selection; input selects no constructor.
- rows
- Only fixed normal and harmless field/type/context comparisons.
- runtimeLedger
- Differences between data, class behavior and authorization.
Fixed JSON and an approved Book class; no unsafe loader, gadget, runtime type selector, endpoint or side effect runs.
Two reality checks
JSON.parse returns a trusted domain object.
Parsing produces plain values; schema, context and constructor projection are separate decisions.
A pure data format solves permission problems.
Pure data narrows behavior exposure; business permission is still required.
YOUR TURN
Work through this story.
Predict the outcome, find the evidence boundary, and explain it in your own words.
JSON contains pageCount="12" as a string. Does this Book-reconstruction profile coerce it and construct the object?
- Yes. Every numeric-looking string automatically becomes a trusted Book.
- No. expectedConstructed=false and body=null.
Read the explained answer
No. expectedConstructed=false and body=null. — This profile requires a numeric pageCount. JSON parsing does not make the string the expected type.
Does JSON parsing load the Book prototype and caption method from the input?
Selected lesson artifact fields; teaching example
- runtimeLedger
- {"parsedJSONHasBookPrototype":false,"textSelectsConstructor":false,"methodLoadedFromText":false,"freezeIsAuthorization":false,"duplicateKeyParserExecuted":false}
- pipeline
- ["JSON values","closed typed DTO","current authorization context","explicit three-field projection","trusted fixed Book constructor","plain caption"]
- No. The approved Book constructor is a fixed application choice.
- Yes. JSON object fields select runtime classes and methods.
Read the explained answer
No. The approved Book constructor is a fixed application choice. — parsedJSONHasBookPrototype=false, textSelectsConstructor=false and methodLoadedFromText=false. A fixed constructor follows explicit three-field projection.
The normal shape is valid, but context-missing stops construction. Why is rejecting unknown subtitle not a universal JSON rule?
Read the explained answer
This profile chooses unknownFieldMode=reject; other contracts may explicitly choose preserve or ignore. JSON itself does not prescribe business fields. A valid DTO still needs current read context; without it, construction and delivery stop. Freezing an object grants no permission. This is fixed trusted Book reconstruction, not an unsafe deserializer, DOM or persistence execution.
□ I tied unknown-field behavior to this contract.
□ I separated object shape/freeze from current authorization.
Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples
Sources and scope
- RFC8259 JSON§3 Values; §4 Objects / member uniqueness · §9 Parsers / limits; §12 Security Considerations
- MDN JSON.parseSyntax/return value; Description: reviver parameter
- OWASP Deserialization Cheat SheetIntroduction / What is Deserialization · Language-Agnostic Methods: Using Alternative Data Formats / pure data DTO