The quick download:
JSON Patch lets you update specific fields in ASP.NET Core APIs without replacing the entire resource.
-
JSON Patch (RFC 6902) supports six operations: add, remove, replace, move, copy, and test, each with specific path and value requirements.
-
The .NET 10+ System.Text.Json package differs from Newtonsoft.Json, so review dynamic type support and serializer behavior before migrating.
-
Production APIs must validate permitted operations, restrict sensitive paths, and check model state after applying patches to avoid security gaps.
-
Combine JSON Patch validation with API monitoring to catch authentication errors, malformed responses, and latency issues before users do.
JSON Patch is a compact, standardized way to describe changes to a JSON document. It pairs well with REST APIs that expose fine-grained updates instead of full-resource replacements.
This guide shows how to implement JSON Patch in ASP.NET Core. It walks through every operation with request and response examples, then covers validation, security, and the errors developers face most often. The same REST conventions appear in production APIs, including LogicMonitor’s REST API Developer Guide.
What is JSON Patch?
JSON Patch is a document format defined by RFC 6902 that describes changes to a target JSON document. A JSON Patch document is a JSON array, and each entry describes one change.
Each entry contains a few well-defined members:
- op: the operation to perform.
- path: a JSON Pointer that identifies the target location.
- value: the new value for add, replace, or test.
- from: the source location for move or copy.
Here’s a simple request that changes an animal’s name:
PATCH /api/animals/42
Content-Type: application/json-patch+json
[
{
"op": "replace",
"path": "/name",
"value": "African lion"
}
]JSON Patch and HTTP PATCH are related but not identical. HTTP PATCH is the request method, while JSON Patch is one possible patch-document format. An API that accepts PATCH won’t necessarily accept RFC 6902 documents, so check the endpoint contract before you build the client.
When to Use JSON Patch
JSON Patch fits cases where a client wants to change specific fields rather than replace an entire resource. It’s a strong choice when a client needs to:
- Change a few fields without sending the complete resource.
- Apply several related changes in one request.
- Append, remove, or reorder array entries.
- Check an expected value before making a change.
- Express updates in a consistent, machine-readable format.
For simple resources, a purpose-built update model can be easier to validate and maintain. JSON Patch earns its keep when clients need flexible, field-level updates and the API team enforces strict rules for permitted paths and operations.
ASP.NET Core Prerequisites and Package Choice
This guide assumes you’re comfortable with REST APIs, C#, and ASP.NET Core. Your package choice depends on the .NET version and the serializer you use.
- Starting with .NET 10, the current ASP.NET Core implementation uses System.Text.Json through the Microsoft.AspNetCore.JsonPatch.SystemTextJson package.
- For .NET 9 and earlier, or apps that depend on legacy Newtonsoft.Json behavior, use Microsoft.AspNetCore.Mvc.NewtonsoftJson.
For .NET 10, add the package like this:
dotnet add package Microsoft.AspNetCore.JsonPatch.SystemTextJson
The System.Text.Json implementation isn’t a drop-in replacement for the Newtonsoft.Json version. One notable difference: it doesn’t support dynamic types such as ExpandoObject. Review the Microsoft JSON Patch documentation before you upgrade an existing API.
Download the patch examples (zip) to follow along with the code in this guide.
Sample Resource and Controller
The examples below act on a single animal resource, shown in the screenshot at the end of this section.
In an ASP.NET Core controller, an action accepts a typed JsonPatchDocument<T>, applies it to an update model, validates the result, and persists the approved changes:
[HttpPatch("{id}")]
public IActionResult UpdateAnimal(
int id,
[FromBody] JsonPatchDocument<AnimalUpdateModel> patchDocument)
{
if (patchDocument is null)
{
return BadRequest();
}
var animal = repository.Find(id);
if (animal is null)
{
return NotFound();
}
var updateModel = mapper.Map<AnimalUpdateModel>(animal);
patchDocument.ApplyTo(updateModel, error =>
ModelState.AddModelError(
error.AffectedObject?.GetType().Name ?? "Animal",
error.ErrorMessage));
if (!TryValidateModel(updateModel))
{
return ValidationProblem(ModelState);
}
mapper.Map(updateModel, animal);
repository.SaveChanges();
return NoContent();
}Treat this as a structural example. The exact ApplyTo overload and error-handling code depend on the package and .NET version in your application. The code sample below shows the sample resource used throughout the walkthrough.

How JSON Patch Operations Work
Operations run in order, and RFC 6902 says processing stops when an operation fails. HTTP PATCH is atomic at the request level, so a failed request must not leave a half-finished update.
Don’t rely on ApplyTo to give you that transaction boundary. Microsoft documents that it modifies the target object in place and makes the caller responsible for discarding changes after an error. Apply the document to a temporary update model, inspect patch errors, validate the result, and persist only after the checks succeed.
Different use cases
The sections below cover each operation type with request and response examples, starting with the add operation.
The add operation
The add operation inserts a new value at a target path. It works on strings, objects, and list elements.
String add operation
To add a “name” property, the request needs a value. The images below show the request and the API response.


Object add operation
It can also assign a full object. The image below shows the object add request.

To add a child property, its parent must already exist. For example, /description/conservationStatus fails if /description is null or missing. The image below shows that null-parent error.

Object add operation in a list case (1)
For arrays, use a zero-based index to insert at a specific position. The image below show the request against an initialized list and its response.


Object add operation in a list case (2)
Use – to append to the end of an array. The image below show an append against an uninitialized list and its response. The append marker applies to add only. It isn’t a shortcut for the last item in remove or replace.


The remove operation
The remove operation deletes the value at a target path. It works on string properties and list elements.
String remove operation
This removes the property value at an existing path. The image below show the request and the response.


The target path must exist. If it doesn’t, the operation fails. The images below show a missing-path request and its error response.


Object/Element remove from list operation
To remove the second array entry, address its index. The images below show the list-removal request and its response.


With typed C# models, removing a property commonly assigns its default CLR value rather than deleting the property definition. Test nullable and non-nullable fields against the package version your API uses.
The replace operation
The replace operation runs as two operations in sequence: remove, then add. It removes the value at the path and adds the new value at the same location.
String & object replace operation
The images below show the request and the response.


Object replace operation in a list
Unlike add, replace requires the target to exist. For an array, specify the exact index. The image below shows a replace against a single list element.

Array replace operation in a list
To replace one array or list property with another, use this request. The images below show the full-array replace request and its response.


Use replace when the existence of the target is a precondition. Use add when creating a new object member or overwriting an existing one is acceptable.
The move/copy operation
Move and copy use the same request shape and behave alike, except for one step. Move copies the value from the “from” location to the “path” location, then removes it from “from”. Copy copies the value from “from” to “path” and leaves the source unchanged. Because repeated copy operations can consume significant memory, limit patch-document size and operation count. The images below show the request and response.


The test operation
The test operation checks the value at the path field. If the check succeeds it returns “200 OK”, otherwise it returns “400 Bad Request”. You can run it before updating any fields, and it’s useful when combined with other operations to check a condition first.
If the test fails, the whole patch document fails. The endpoint must discard the temporary update model so no earlier mutation reaches storage. The HTTP error response depends on the API implementation, since RFC 6902 doesn’t require one specific status code for every failure.
The images below show the test request and its response.


The test operation guards against stale assumptions, though it’s not a complete concurrency strategy. For competing updates, consider conditional requests with entity tags and If-Match.
The multiple operation
A single request can carry multiple operations, and they can each be a different type.
Because order matters, review the dependencies between entries. A later operation may refer to a path created, moved, or removed earlier in the same document. The images below show the multi-operation request and its response.


Operation control
The JSON Patch NuGet package exposes a list of supported operations, so you can restrict which operations an API endpoint accepts, rejecting risky ones such as move or copy when an endpoint doesn’t need them. The image below shows operation control in code.

Uses of JSON Patch document with dynamic objects
Dynamic objects work with the Newtonsoft.Json implementation. The .NET 10 System.Text.Json implementation doesn’t support dynamic types such as ExpandoObject, so plan accordingly when you target the newer serializer. The image below shows a dynamic-object example.

Other uses of JSON Patch document
You can also apply a JSON Patch document to change a JSON document directly, without a controller action in the middle. The images below show that approach and its result.


Validate operations before applying them
Never apply an untrusted patch document directly to a persistence entity. Validate the request against an explicit policy first. A production API should check:
- Authentication and authorization for the endpoint.
- Permitted operations.
- Permitted paths.
- Maximum request size and operation count.
- Array indexes and collection growth.
- Data types, ranges, formats, and business rules.
- Model validity after the patch.
Use a dedicated update model that exposes only the fields clients may change. Block identifiers, ownership fields, permission flags, computed values, and other sensitive properties. For tighter control, reject risky operations such as move or copy when the endpoint doesn’t need them.
Microsoft notes that JSON Patch carries inherent security risks that the ASP.NET Core implementation doesn’t mitigate for your application. Threat modeling and request validation stay the API team’s responsibility.
Common JSON Patch errors
Most failures trace back to a small set of mistakes:
- Sending application/json instead of application/json-patch+json.
- Using a path that doesn’t start with /.
- Targeting a missing parent object.
- Using replace, remove, move, or copy with a missing source or target.
- Using – with an operation other than add.
- Forgetting JSON Pointer escaping: use ~1 for / and ~0 for ~ inside a path token.
- Assuming property-name casing behaves the same across serializers.
- Applying changes before checking authorization and business rules.
Log validation failures with enough context to diagnose bad requests. Don’t record secrets or full sensitive payloads.
Monitoring JSON Patch API operations with LogicMonitor
A JSON Patch request can pass development tests and still fail in production because of authentication errors, invalid response data, latency, network conditions, or downstream dependencies. Teams therefore need to verify more than endpoint availability: they must confirm that each API operation completes successfully, returns the correct status and payload, and works across locations and multi-step workflows.
LogicMonitor API monitoring runs scheduled checks against endpoints and workflows by helping teams detect failed updates, unexpected responses, and performance regressions. For teams integrating with LogicMonitor resources, the LogicMonitor REST API developer guide documents supported HTTP methods, including PATCH.
Monitor your JSON Patch endpoints from development through production.
LogicMonitor API monitoring validates response codes, payloads, and performance across multi-step API workflows. Detect failed patches, unexpected status codes, and latency spikes before they affect your users.
FAQs
What content type should I use for JSON Patch requests?
Use application/json-patch+json as the Content-Type header. This is one of the most common errors developers encounter. Sending application/json instead will cause the request to fail because the server expects the RFC 6902 patch document format.
Should I use System.Text.Json or Newtonsoft.Json for JSON Patch in ASP.NET Core?
For .NET 10 and later, use the Microsoft.AspNetCore.JsonPatch.SystemTextJson package. For .NET 9 and earlier, or if your application relies on dynamic types like ExpandoObject, use Microsoft.AspNetCore.Mvc.NewtonsoftJson. The System.Text.Json implementation does not support dynamic types.
How do I secure JSON Patch endpoints against malicious requests?
Apply a patch document to a dedicated update model that exposes only permitted fields. Validate authentication, permitted operations, and permitted paths before applying changes. Block identifiers, ownership fields, and computed values. Set limits on request size and operation count to prevent abuse.




