feat(std/json-patch): JSON Patch (RFC 6902) with atomic apply #584
Loading…
Reference in a new issue
No description provided.
Delete branch "loop/581-json-patch"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #581
Task
Step 2 of #81:
std/json-patch, JSON Patch (RFC 6902) onJsonValue, with the public json-patch-tests suite run in full.What and why
std/json-patch:JsonPatch(a list ofPatchOperation),PatchOperation(add, remove, replace, move, copy, test),PatchErrorandPatchProblem.JsonPatchreads from and writes to the RFC array throughEncodeandDecode; a decoding error names the position of the operation.applyis atomic and never changes the document it is given. The first failing operation gives aPatchError(position, operation, pointer, kind, detail).addinserts into arrays (index up to the length, or-; a larger index is an error) and replaces the document at"";removeandreplaceneed an existing target;moveis remove then add and refuses to move into its own child;copyis get then add;testcompares as section 4.6 says.docs/standard-library/json-patch.md, index entry, ROADMAP row (RFC 6902 done, RFC 7396 open),skills/regenerated.Decision for review:
Decoder.untypedJsonValuehadEncodebut noDecode, so a patch (valueis any JSON) could not be decoded through the pull vocabulary. I added a defaulted methodDecoder.untyped()(answers aDecodeErrorunless a format overrides it),ValueDecoder.untyped()(hands over the bufferedEncodedValue) andextend JsonValue with Decode. Every buffering format gets it; a format that needs the type keeps the default. This also lets a record have aJsonValuefield. It has its own tests instd/json/tests/untyped.test.trb.Suite and exclusions
tests/suite-cases.trbis generated fromtests.jsonandspec_tests.jsonat commit2a928f9044aad35c74e2788d498bcf2c6b91adea, 112 cases, one test per case insuite.test.trb.disabled. Two are valid and run like any other. Of the two that expect a refusal for anopmember written twice,spec_tests#13 passes anyway (the kept member is aremoveof a member that is not there).tests#85 cannot be refused: a JSON object is read into a map that keeps one member per name, so the patch is read as a validmove. It is the one exclusion, with its reason; the test still applies the patch, so the exclusion fails loudly if a reader ever learns to refuse repeated members.Test
torb:std/json-patch/tests/json-patch.test.trb49 passed,suite.test.trb115 passed,std/json/tests/untyped.test.trb4 passed;torb formaton every touched file;torb docs sourceon the new package; the two examples of the page run with the printed output.sh tools/check-commits.sh origin/main: clean.sh tools/gates.sh a: forge CI (not run locally).std/json-patchwith RFC 6902 JSON Patch and the json-patch-tests suite (step 2 of #81) #581std/json-patchwith RFC 6902 JSON Patch and the json-patch-tests suite (step 2 of #81) #581std/json-patchwith RFC 6902 JSON Patch and the json-patch-tests suite (step 2 of #81) #581std/json-patchwith RFC 6902 JSON Patch and the json-patch-tests suite (step 2 of #81) #581703b9f915e194907350aChecklist on
1949073:Decoder.untyped/JsonValueDecode. CI success on this head (tier A, gates, bootstrap, pdisc, commit messages).-, move into own child refused, move onto itself a no-op after the existence check,testper 4.6, whole-document remove refused, index token validation incl. leading zeros and overlong digits).applyworks on immutable values, so it is atomic.Decoder.untypedaddition is the minimum needed to decodevalue, stated and tested in the PR.Non-blocking:
untyped(); add it in a follow-up so the design record matches the library.