{"id":19746901,"url":"https://github.com/finitereality/finite.aspnetcore.jsonpatch","last_synced_at":"2026-06-17T09:31:08.668Z","repository":{"id":135890611,"uuid":"358866763","full_name":"FiniteReality/Finite.AspNetCore.JsonPatch","owner":"FiniteReality","description":"JSON Patch for ASP.NET Core using System.Text.Json","archived":false,"fork":false,"pushed_at":"2021-04-17T12:21:12.000Z","size":22,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-23T09:03:29.188Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FiniteReality.png","metadata":{"files":{"readme":"docs/README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-17T11:56:58.000Z","updated_at":"2022-05-15T03:31:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"7e4f33ef-0c60-4e5c-bb3c-57f486098a94","html_url":"https://github.com/FiniteReality/Finite.AspNetCore.JsonPatch","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/FiniteReality/Finite.AspNetCore.JsonPatch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FiniteReality%2FFinite.AspNetCore.JsonPatch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FiniteReality%2FFinite.AspNetCore.JsonPatch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FiniteReality%2FFinite.AspNetCore.JsonPatch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FiniteReality%2FFinite.AspNetCore.JsonPatch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FiniteReality","download_url":"https://codeload.github.com/FiniteReality/Finite.AspNetCore.JsonPatch/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FiniteReality%2FFinite.AspNetCore.JsonPatch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34443229,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T02:16:11.722Z","updated_at":"2026-06-17T09:31:08.648Z","avatar_url":"https://github.com/FiniteReality.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Finite.AspNetCore.JsonPatch #\n\nA simple(ish) JSON Patch implementation for ASP.NET Core using System.Text.Json\ninstead of Newtonsoft.Json\n\n## Why? ##\n\nThe \"built-in\" JSON Patch library requires Newtonsoft.Json... I don't want to\nuse Newtonsoft.Json.\n\n## How? ##\n\nIn Startup:\n```cs\nvoid ConfigureServiceS(IServiceCollection services)\n{\n    _ = services.AddControllers()\n        .AddJsonOptions(options =\u003e\n        {\n            options.JsonSerializerOptions.Converters.Add(\n                new JsonPatchConverter());\n            options.JsonSerializerOptions.Converters.Add(\n                new JsonPointerConverter());\n        })\n}\n```\nIn your controller, use something like:\n```cs\n// N.B. this isn't error checked or anything, so it's probably broken.\n// demonstrative purposes only!\n[HttpPatch]\npublic IActionResult Patch(\n    [FromBody, Required]JsonPatch patch)\n{\n    // or loaded from somewhere\n    using var currentValue = JsonDocument.Parse(\"{}\");\n    using var writer = new Utf8JsonWriter(Response.BodyWriter);\n\n    if (!patch.TryApply(writer,\n        currentValue.RootElement))\n    {\n        // patch didn't apply\n        return BadRequest();\n    }\n\n    // flush the writer\n    writer.Flush();\n    return Ok();\n}\n\n// Or:\n[HttpPatch]\npublic async Task\u003cIActionResult\u003e Patch(\n    [FromBody, Required]JsonPatch patch)\n{\n    // GetJsonDocumentFromDatabase should likely register the JsonDocument for\n    // dispose (Response.RegisterForDispose)\n    var currentValue = await GetJsonDocumentFromDatabaseAsync();\n    var array = new ArrayBufferWriter\u003cbyte\u003e();\n    using var writer = new Utf8JsonWriter(array);\n\n    if (!patch.TryApply(writer,\n        currentValue.RootElement))\n    {\n        // patch didn't apply\n        return BadRequest();\n    }\n\n    // flush the writer so we can re-parse it\n    writer.Flush();\n\n    // parse the output as a json document\n    using var finalValue = JsonDocument.Parse(array.WrittenMemory);\n    await SaveToDatabaseAsync(finalValue);\n\n    // notify other people that the data in the database has changed\n    // (e.g. via pub/sub)\n    await BroadcastChanges(finalValue);\n\n    return NoContent();\n}\n```\n\n### Why Utf8JsonWriter as a parameter to TryApply? ###\nI didn't want to expose the internal mutable JSON tree (see MutableJson.cs)\nsince it's not perfect and probably doesn't work like you expect:\n- MutableJsonValue purely represents the tree in a JSON document\n- It refers directly to JsonElement-s owned by other JsonDocuments and does not\n  copy them.\n  - A MutableJsonElement refers to either a JsonDocument owned by the JsonPatch\n    or a JsonElement owned by the passed root element in TryApply.\n- It is very easy to get into a situation where you get use-after-dispose\n\nAs ugly as the current approach is, it mostly guarantees that TryApply won't\nthrow, and will always produce valid JSON if it returns true.\n\n## TODO ##\n- Use built-in writable DOM: https://github.com/dotnet/designs/pull/163\n  - When the above is merged, make TryApply have an `out JsonNode` parameter","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinitereality%2Ffinite.aspnetcore.jsonpatch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffinitereality%2Ffinite.aspnetcore.jsonpatch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinitereality%2Ffinite.aspnetcore.jsonpatch/lists"}