From 54a74b0215fcdd20c17dbe5e588090a9ac133cde Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 31 Jul 2025 12:22:32 +0300 Subject: [PATCH] docs: document JSON properties (#13099) --- .../generated/generated-admin-sidebar.mjs | 6 + .../generated/generated-store-sidebar.mjs | 6 + www/apps/api-reference/markdown/admin.mdx | 220 ++++++++++++++ www/apps/api-reference/markdown/store.mdx | 255 ++++++++++++++++- .../data-models/json-properties/page.mdx | 237 +++++++++++++++ .../data-models/properties/page.mdx | 4 +- www/apps/book/generated/edit-dates.mjs | 5 +- www/apps/book/generated/sidebar.mjs | 30 +- www/apps/book/public/llms-full.txt | 269 +++++++++++++++++- www/apps/book/sidebar.mjs | 5 + .../methods/update/page.mdx | 34 +++ www/apps/resources/generated/edit-dates.mjs | 2 +- .../generated-commerce-modules-sidebar.mjs | 8 + .../generated/generated-tools-sidebar.mjs | 8 + 14 files changed, 1072 insertions(+), 17 deletions(-) create mode 100644 www/apps/book/app/learn/fundamentals/data-models/json-properties/page.mdx diff --git a/www/apps/api-reference/generated/generated-admin-sidebar.mjs b/www/apps/api-reference/generated/generated-admin-sidebar.mjs index 6b668773db..85fa41cef3 100644 --- a/www/apps/api-reference/generated/generated-admin-sidebar.mjs +++ b/www/apps/api-reference/generated/generated-admin-sidebar.mjs @@ -20,6 +20,12 @@ const generatedgeneratedAdminSidebarSidebar = { "path": "http-compression", "loaded": true }, + { + "type": "link", + "title": "Manage Metadata", + "path": "manage-metadata", + "loaded": true + }, { "type": "link", "title": "Select Fields and Relations", diff --git a/www/apps/api-reference/generated/generated-store-sidebar.mjs b/www/apps/api-reference/generated/generated-store-sidebar.mjs index 556852701d..94325bcb4b 100644 --- a/www/apps/api-reference/generated/generated-store-sidebar.mjs +++ b/www/apps/api-reference/generated/generated-store-sidebar.mjs @@ -26,6 +26,12 @@ const generatedgeneratedStoreSidebarSidebar = { "path": "http-compression", "loaded": true }, + { + "type": "link", + "title": "Manage Metadata", + "path": "manage-metadata", + "loaded": true + }, { "type": "link", "title": "Select Fields and Relations", diff --git a/www/apps/api-reference/markdown/admin.mdx b/www/apps/api-reference/markdown/admin.mdx index b866601c15..e26980bc4b 100644 --- a/www/apps/api-reference/markdown/admin.mdx +++ b/www/apps/api-reference/markdown/admin.mdx @@ -483,6 +483,226 @@ x-no-compression: false +## Manage Metadata + +Many data models in Medusa, such as products and carts, have a `metadata` field that allows you to store custom information in key-value pairs. + +When setting or updating the `metadata` field using the relevant API routes, Medusa will merge the new metadata with the existing metadata. + + + +The instructions in this section apply to any [JSON property in a data model](!docs!/learn/fundamentals/data-models/json-properties). + + + + + + + + + + + +### Accepted Values in Metadata + +The `metadata` is an object of key-value pairs, where the keys are strings and the values can be one of the following types: + +- String + - An empty string deletes the property from the metadata. +- Number +- Boolean +- Date +- Object +- Arrays of any of the above types + +The `metadata` is not validated, so you can store any custom data in it. + + + + + +```ts title="Metadata Example" +{ + "metadata": { + "category": "electronics", + "views": 1500, + "is_featured": true, + "tags": ["new", "sale"], + "details": { + "warranty": "2 years", + "origin": "USA" + } + } +} +``` + + + + + + + + + +### Add or Update New Property in Metadata + +To add or update a property in the `metadata`, pass the property in the request body as a key-value pair. This won't affect existing properties in the metadata. + + + + + + + + + +```js title="Add new metadata property" +sdk.admin.product.update("prod_123", { + metadata: { + new_property: "value" + } +}) +``` + + + + + +```json title="Result" +{ + "id": "prod_123", + "metadata": { + "new_property": "value", + "old_property": "value" + } +} +``` + + + + + + + + + + + + + +### Update Nested Objects in Metadata + +When updating a nested object in the `metadata`, you must pass the entire object in the request body. + +Medusa doesn't merge nested objects, so if you pass a partial object, the existing properties in the nested object will be removed. + + + + + + + + + +```js title="Update nested object in metadata" +sdk.admin.product.update("prod_123", { + metadata: { + nested_object: { + property1: "value1", + property2: "value2" + } + } +}) +``` + + + + + +```json title="Result" +{ + "id": "prod_123", + "metadata": { + "nested_object": { + "property1": "value1", + "property2": "value2" + } + } +} +``` + + + + + + + + + + + + + +### Remove Property from Metadata + +To remove a property from the `metadata`, pass the property in the request body with an empty string value. This will remove the property from the `metadata` without affecting other properties. + + + + + + + + + + + +```js title="Remove metadata property" +sdk.admin.product.update("prod_123", { + metadata: { + property_to_remove: "" + } +}) +``` + + + + + +```json title="Result" +{ + "id": "prod_123", + "metadata": { + "other_property": "value" + } +} +``` + + + + + + + + + + + + + + + + + ## Select Fields and Relations diff --git a/www/apps/api-reference/markdown/store.mdx b/www/apps/api-reference/markdown/store.mdx index 6c5b8f58ab..401a52f0b8 100644 --- a/www/apps/api-reference/markdown/store.mdx +++ b/www/apps/api-reference/markdown/store.mdx @@ -441,6 +441,253 @@ x-no-compression: false +## Manage Metadata + +Many data models in Medusa, such as products and carts, have a `metadata` field that allows you to store custom information in key-value pairs. + +When setting or updating the `metadata` field using the relevant API routes, Medusa will merge the new metadata with the existing metadata. + + + +The instructions in this section apply to any [JSON property in a data model](!docs!/learn/fundamentals/data-models/json-properties). + + + + + + + + + + + +### Accepted Values in Metadata + +The `metadata` is an object of key-value pairs, where the keys are strings and the values can be one of the following types: + +- String + - An empty string deletes the property from the metadata. +- Number +- Boolean +- Date +- Object +- Arrays of any of the above types + +The `metadata` is not validated, so you can store any custom data in it. + + + + + +```ts title="Metadata Example" +{ + "metadata": { + "category": "electronics", + "views": 1500, + "is_featured": true, + "tags": ["new", "sale"], + "details": { + "warranty": "2 years", + "origin": "USA" + } + } +} +``` + + + + + + + + + +### Add or Update New Property in Metadata + +To add or update a property in the `metadata`, pass the property in the request body as a key-value pair. This won't affect existing properties in the metadata. + + + + + + + + + +```js title="Add new metadata property" +sdk.store.cart.updateLineItem( + "cart_123", + "li_123", + { + metadata: { + new_property: "value" + } + } +) +``` + + + + + +```json title="Result" +{ + "id": "cart_123", + "items": [ + { + "id": "li_123", + "metadata": { + "new_property": "value", + "old_property": "value" + } + } + ] +} +``` + + + + + + + + + + + + + +### Update Nested Objects in Metadata + +When updating a nested object in the `metadata`, you must pass the entire object in the request body. + +Medusa doesn't merge nested objects, so if you pass a partial object, the existing properties in the nested object will be removed. + + + + + + + + + +```js title="Update nested object in metadata" +sdk.store.cart.updateLineItem( + "cart_123", + "li_123", + { + metadata: { + nested_object: { + property1: "value1", + property2: "value2" + } + } + } +) +``` + + + + + +```json title="Result" +{ + "id": "cart_123", + "items": [ + { + "id": "li_123", + "metadata": { + "nested_object": { + "property1": "value1", + "property2": "value2" + } + } + } + ] +} +``` + + + + + + + + + + + + + +### Remove Property from Metadata + +To remove a property from the `metadata`, pass the property in the request body with an empty string value. This will remove the property from the `metadata` without affecting other properties. + + + + + + + + + + + +```js title="Remove metadata property" +sdk.store.cart.updateLineItem( + "cart_123", + "li_123", + { + metadata: { + property_to_remove: "" + } + } +) +``` + + + + + +```json title="Result" +{ + "id": "cart_123", + "items": [ + { + "id": "li_123", + "metadata": { + "other_property": "value" + } + } + ] +} +``` + + + + + + + + + + + + + + + + + ## Select Fields and Relations @@ -1167,6 +1414,10 @@ This sorts the products by their `created_at` field in the descending order. + + + + @@ -1184,10 +1435,10 @@ Refer to [this guide](!docs!/learn/customization/extend-features/extend-create-p diff --git a/www/apps/book/app/learn/fundamentals/data-models/json-properties/page.mdx b/www/apps/book/app/learn/fundamentals/data-models/json-properties/page.mdx new file mode 100644 index 0000000000..0eff132453 --- /dev/null +++ b/www/apps/book/app/learn/fundamentals/data-models/json-properties/page.mdx @@ -0,0 +1,237 @@ +export const metadata = { + title: `${pageNumber} JSON Properties in Data Models`, +} + +# {metadata.title} + +In this chapter, you'll learn how to use and manage [JSON properties](../properties/page.mdx#json) in data models. + +## What is a JSON Property? + +A JSON property in a data model is a flexible object that can contain various types of values. + +For example, you can create a `Brand` data model with a `metadata` JSON property to store additional information about the brand: + +```ts highlights={[["6"]]} +import { model } from "@medusajs/framework/utils" + +const Brand = model.define("brand", { + id: model.id().primaryKey(), + name: model.text(), + metadata: model.json(), +}) +``` + +### Accepted Values in JSON Property + +JSON properties are made up of key-value pairs. The keys are strings, and the values can be one of the following types: + +- **Strings**: Text values. + - Empty strings remove the property from the JSON object. Learn more in the [Remove a Property from the JSON Property](#remove-a-property-from-the-json-property) section. +- **Numbers**: Numeric values. +- **Booleans**: `true` or `false` values. +- **Nested Objects**: Objects within objects. +- **Arrays**: Lists of values of any of the above types. + +For example, a `metadata` JSON property can look like this: + +```json +{ + "category": "electronics", + "views": 1500, + "is_featured": true, + "tags": ["new", "sale"], + "details": { + "warranty": "2 years", + "origin": "USA" + } +} +``` + +### What are JSON Properties Useful For? + +JSON properties allow you to store flexible and dynamic data structures that can evolve over time without requiring changes to the database schema. + +Most data models in Medusa's Commerce Modules have a `metadata` property that is a JSON object. `metadata` allows you to store custom information that is not part of the core data model. + +Some examples of data to store in JSON properties: + +- Custom gift message for line items in an order. +- Product's ID in a third-party system. +- Brand's category or tags. + +### What are JSON Properties Not Useful For? + +JSON properties are not suitable for structured data that requires strict validation or relationships with other data models. + +For example, if you want to re-use brands across different products, it's better to create a `Brand` data model and [define a link](../../module-links/page.mdx) to the `Product` data model instead of storing brand information in the product's `metadata` JSON property. + +--- + +## How to Manage JSON Properties? + +### How Medusa Updates JSON Properties + +Consider a Brand Module with a `Brand` data model as shown [in the previous section](#what-are-json-properties). The [module's service](../../modules/page.mdx#2-create-service) will extend `MedusaService`, which generates methods like [updateBrands](!resources!/service-factory-reference/methods/update) to update a brand. + +When you pass a JSON property in the `updateBrands` method, Medusa will merge the provided JSON object with the existing one in the database. So, only the properties you pass will be updated, and the rest will remain unchanged. + +The following sections show examples of how to add, update, and remove properties in a JSON property. + + + +The following examples assume you have a `brandModuleService` that is resolved from the [Medusa container](../../medusa-container/page.mdx). For example: + +```ts +const brandModuleService = container.resolve(BRAND_MODULE) +``` + + + +### Add a Property to the JSON Property + +Continuing with the Brand example, to add a `category` property to the `metadata` property, pass the new property in the `update` or `create` methods: + +```ts +const brand = await brandModuleService.updateBrands({ + id: "brand_123", + metadata: { + category: "electronics", + } +}) +``` + +The brand record will now have the `metadata` property updated to include the new `category` property: + +```json title="Result" +{ + "id": "brand_123", + "metadata": { + "category": "electronics" + } +} +``` + +If you want to add another `is_featured` property later, you can do so by passing it in the update method again without affecting the existing properties: + +```ts +const brand = await brandModuleService.updateBrands({ + id: "brand_123", + metadata: { + is_featured: true, + } +}) +``` + +The brand record will now have the `metadata` property updated to include both `category` and `is_featured` properties: + +```json title="Result" +{ + "id": "brand_123", + "metadata": { + "category": "electronics", + "is_featured": true + } +} +``` + +### Update an Existing Property in the JSON Property + +To update an existing property in the JSON property, pass the updated value in the `update` method. + +Continuing with the Brand example, to update the `category` property in the `metadata`: + +```ts +const brand = await brandModuleService.updateBrands({ + id: "brand_123", + metadata: { + category: "home appliances", + } +}) +``` + +The brand record will now have the `metadata` property updated to reflect the new `category` value, and existing properties will remain unchanged: + +```json title="Result" +{ + "id": "brand_123", + "metadata": { + "category": "home appliances", + "is_featured": true + } +} +``` + +### Caveat: Updating Nested Objects + +If you want to update a nested object within the JSON property, you need to provide the entire nested object in the update method. + +For example, consider that you have a `details` object within the `metadata`: + +```json +{ + "id": "brand_123", + "metadata": { + "category": "electronics", + "details": { + "warranty": "1 year", + "origin": "China" + } + } +} +``` + +To update the `warranty` property within the `details` object, you need to provide the entire `details` object in the update method: + +```ts +const brand = await brandModuleService.updateBrands({ + id: "brand_123", + metadata: { + details: { + warranty: "2 years", + origin: "China" + } + } +}) +``` + +The brand record will now have the `metadata` property updated with the new `warranty` value: + +```json title="Result" +{ + "id": "brand_123", + "metadata": { + "category": "electronics", + "details": { + "warranty": "2 years", + "origin": "China" + } + } +} +``` + +### Remove a Property from the JSON Property + +To remove a property from the JSON property, you can pass an empty string as the value of the property in the update method. + +For example, to remove the `is_featured` property from the `metadata`: + +```ts +const brand = await brandModuleService.updateBrands({ + id: "brand_123", + metadata: { + is_featured: "", + } +}) +``` + +The brand record will now have the `metadata` property updated to remove the `is_featured` property: + +```json title="Result" +{ + "id": "brand_123", + "metadata": { + "category": "home appliances" + } +} +``` diff --git a/www/apps/book/app/learn/fundamentals/data-models/properties/page.mdx b/www/apps/book/app/learn/fundamentals/data-models/properties/page.mdx index fd0bfec50a..1ea9ef7170 100644 --- a/www/apps/book/app/learn/fundamentals/data-models/properties/page.mdx +++ b/www/apps/book/app/learn/fundamentals/data-models/properties/page.mdx @@ -220,7 +220,7 @@ export default Post ### json -The `json` method defines a property whose value is a stringified JSON object. +The `json` method defines a property whose value is stored as a stringified JSON object in the database. For example: @@ -237,6 +237,8 @@ const Post = model.define("post", { export default Post ``` +Learn more in the [JSON Properties](../json-properties/page.mdx) chapter. + ### array The `array` method defines an array of strings property. diff --git a/www/apps/book/generated/edit-dates.mjs b/www/apps/book/generated/edit-dates.mjs index e1b2d470e2..63edcd9062 100644 --- a/www/apps/book/generated/edit-dates.mjs +++ b/www/apps/book/generated/edit-dates.mjs @@ -115,7 +115,7 @@ export const generatedEditDates = { "app/learn/configurations/ts-aliases/page.mdx": "2025-07-23T15:32:18.008Z", "app/learn/production/worker-mode/page.mdx": "2025-07-18T15:19:45.352Z", "app/learn/fundamentals/module-links/read-only/page.mdx": "2025-07-25T07:58:54.327Z", - "app/learn/fundamentals/data-models/properties/page.mdx": "2025-07-25T13:40:28.866Z", + "app/learn/fundamentals/data-models/properties/page.mdx": "2025-07-31T08:22:20.431Z", "app/learn/fundamentals/framework/page.mdx": "2025-06-26T14:26:22.120Z", "app/learn/fundamentals/api-routes/retrieve-custom-links/page.mdx": "2025-07-14T10:24:32.582Z", "app/learn/fundamentals/workflows/errors/page.mdx": "2025-04-25T14:26:25.000Z", @@ -126,5 +126,6 @@ export const generatedEditDates = { "app/learn/installation/docker/page.mdx": "2025-07-23T15:34:18.530Z", "app/learn/fundamentals/generated-types/page.mdx": "2025-07-25T13:17:35.319Z", "app/learn/introduction/from-v1-to-v2/page.mdx": "2025-07-30T08:13:48.592Z", - "app/learn/debugging-and-testing/debug-workflows/page.mdx": "2025-07-30T13:45:14.117Z" + "app/learn/debugging-and-testing/debug-workflows/page.mdx": "2025-07-30T13:45:14.117Z", + "app/learn/fundamentals/data-models/json-properties/page.mdx": "2025-07-31T08:38:55.014Z" } \ No newline at end of file diff --git a/www/apps/book/generated/sidebar.mjs b/www/apps/book/generated/sidebar.mjs index 5c2972e06c..0eea209e41 100644 --- a/www/apps/book/generated/sidebar.mjs +++ b/www/apps/book/generated/sidebar.mjs @@ -513,6 +513,16 @@ export const generatedSidebars = [ "chapterTitle": "3.5.2. Properties", "number": "3.5.2." }, + { + "loaded": true, + "isPathHref": true, + "type": "link", + "path": "/learn/fundamentals/data-models/json-properties", + "title": "JSON Properties", + "children": [], + "chapterTitle": "3.5.3. JSON Properties", + "number": "3.5.3." + }, { "loaded": true, "isPathHref": true, @@ -520,8 +530,8 @@ export const generatedSidebars = [ "path": "/learn/fundamentals/data-models/relationships", "title": "Relationships", "children": [], - "chapterTitle": "3.5.3. Relationships", - "number": "3.5.3." + "chapterTitle": "3.5.4. Relationships", + "number": "3.5.4." }, { "loaded": true, @@ -530,8 +540,8 @@ export const generatedSidebars = [ "path": "/learn/fundamentals/data-models/manage-relationships", "title": "Manage Relationships", "children": [], - "chapterTitle": "3.5.4. Manage Relationships", - "number": "3.5.4." + "chapterTitle": "3.5.5. Manage Relationships", + "number": "3.5.5." }, { "loaded": true, @@ -540,8 +550,8 @@ export const generatedSidebars = [ "path": "/learn/fundamentals/data-models/index", "title": "Define Index", "children": [], - "chapterTitle": "3.5.5. Define Index", - "number": "3.5.5." + "chapterTitle": "3.5.6. Define Index", + "number": "3.5.6." }, { "loaded": true, @@ -550,8 +560,8 @@ export const generatedSidebars = [ "path": "/learn/fundamentals/data-models/check-constraints", "title": "Check Constraints", "children": [], - "chapterTitle": "3.5.6. Check Constraints", - "number": "3.5.6." + "chapterTitle": "3.5.7. Check Constraints", + "number": "3.5.7." }, { "loaded": true, @@ -560,8 +570,8 @@ export const generatedSidebars = [ "path": "/learn/fundamentals/data-models/write-migration", "title": "Migrations", "children": [], - "chapterTitle": "3.5.7. Migrations", - "number": "3.5.7." + "chapterTitle": "3.5.8. Migrations", + "number": "3.5.8." } ], "chapterTitle": "3.5. Data Models", diff --git a/www/apps/book/public/llms-full.txt b/www/apps/book/public/llms-full.txt index 9e41bcd17a..5922c8aac4 100644 --- a/www/apps/book/public/llms-full.txt +++ b/www/apps/book/public/llms-full.txt @@ -9604,6 +9604,237 @@ class BlogModuleService extends MedusaService({ Post }) { ``` +# JSON Properties in Data Models + +In this chapter, you'll learn how to use and manage [JSON properties](https://docs.medusajs.com/learn/fundamentals/data-models/properties#json/index.html.md) in data models. + +## What is a JSON Property? + +A JSON property in a data model is a flexible object that can contain various types of values. + +For example, you can create a `Brand` data model with a `metadata` JSON property to store additional information about the brand: + +```ts highlights={[["6"]]} +import { model } from "@medusajs/framework/utils" + +const Brand = model.define("brand", { + id: model.id().primaryKey(), + name: model.text(), + metadata: model.json(), +}) +``` + +### Accepted Values in JSON Property + +JSON properties are made up of key-value pairs. The keys are strings, and the values can be one of the following types: + +- **Strings**: Text values. + - Empty strings remove the property from the JSON object. Learn more in the [Remove a Property from the JSON Property](#remove-a-property-from-the-json-property) section. +- **Numbers**: Numeric values. +- **Booleans**: `true` or `false` values. +- **Nested Objects**: Objects within objects. +- **Arrays**: Lists of values of any of the above types. + +For example, a `metadata` JSON property can look like this: + +```json +{ + "category": "electronics", + "views": 1500, + "is_featured": true, + "tags": ["new", "sale"], + "details": { + "warranty": "2 years", + "origin": "USA" + } +} +``` + +### What are JSON Properties Useful For? + +JSON properties allow you to store flexible and dynamic data structures that can evolve over time without requiring changes to the database schema. + +Most data models in Medusa's Commerce Modules have a `metadata` property that is a JSON object. `metadata` allows you to store custom information that is not part of the core data model. + +Some examples of data to store in JSON properties: + +- Custom gift message for line items in an order. +- Product's ID in a third-party system. +- Brand's category or tags. + +### What are JSON Properties Not Useful For? + +JSON properties are not suitable for structured data that requires strict validation or relationships with other data models. + +For example, if you want to re-use brands across different products, it's better to create a `Brand` data model and [define a link](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) to the `Product` data model instead of storing brand information in the product's `metadata` JSON property. + +*** + +## How to Manage JSON Properties? + +### How Medusa Updates JSON Properties + +Consider a Brand Module with a `Brand` data model as shown [in the previous section](#what-are-json-properties). The [module's service](https://docs.medusajs.com/learn/fundamentals/modules#2-create-service/index.html.md) will extend `MedusaService`, which generates methods like [updateBrands](https://docs.medusajs.com/resources/service-factory-reference/methods/update/index.html.md) to update a brand. + +When you pass a JSON property in the `updateBrands` method, Medusa will merge the provided JSON object with the existing one in the database. So, only the properties you pass will be updated, and the rest will remain unchanged. + +The following sections show examples of how to add, update, and remove properties in a JSON property. + +The following examples assume you have a `brandModuleService` that is resolved from the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md). For example: + +```ts +const brandModuleService = container.resolve(BRAND_MODULE) +``` + +### Add a Property to the JSON Property + +Continuing with the Brand example, to add a `category` property to the `metadata` property, pass the new property in the `update` or `create` methods: + +```ts +const brand = await brandModuleService.updateBrands({ + id: "brand_123", + metadata: { + category: "electronics", + } +}) +``` + +The brand record will now have the `metadata` property updated to include the new `category` property: + +```json title="Result" +{ + "id": "brand_123", + "metadata": { + "category": "electronics" + } +} +``` + +If you want to add another `is_featured` property later, you can do so by passing it in the update method again without affecting the existing properties: + +```ts +const brand = await brandModuleService.updateBrands({ + id: "brand_123", + metadata: { + is_featured: true, + } +}) +``` + +The brand record will now have the `metadata` property updated to include both `category` and `is_featured` properties: + +```json title="Result" +{ + "id": "brand_123", + "metadata": { + "category": "electronics", + "is_featured": true + } +} +``` + +### Update an Existing Property in the JSON Property + +To update an existing property in the JSON property, pass the updated value in the `update` method. + +Continuing with the Brand example, to update the `category` property in the `metadata`: + +```ts +const brand = await brandModuleService.updateBrands({ + id: "brand_123", + metadata: { + category: "home appliances", + } +}) +``` + +The brand record will now have the `metadata` property updated to reflect the new `category` value, and existing properties will remain unchanged: + +```json title="Result" +{ + "id": "brand_123", + "metadata": { + "category": "home appliances", + "is_featured": true + } +} +``` + +### Caveat: Updating Nested Objects + +If you want to update a nested object within the JSON property, you need to provide the entire nested object in the update method. + +For example, consider that you have a `details` object within the `metadata`: + +```json +{ + "id": "brand_123", + "metadata": { + "category": "electronics", + "details": { + "warranty": "1 year", + "origin": "China" + } + } +} +``` + +To update the `warranty` property within the `details` object, you need to provide the entire `details` object in the update method: + +```ts +const brand = await brandModuleService.updateBrands({ + id: "brand_123", + metadata: { + details: { + warranty: "2 years", + origin: "China" + } + } +}) +``` + +The brand record will now have the `metadata` property updated with the new `warranty` value: + +```json title="Result" +{ + "id": "brand_123", + "metadata": { + "category": "electronics", + "details": { + "warranty": "2 years", + "origin": "China" + } + } +} +``` + +### Remove a Property from the JSON Property + +To remove a property from the JSON property, you can pass an empty string as the value of the property in the update method. + +For example, to remove the `is_featured` property from the `metadata`: + +```ts +const brand = await brandModuleService.updateBrands({ + id: "brand_123", + metadata: { + is_featured: "", + } +}) +``` + +The brand record will now have the `metadata` property updated to remove the `is_featured` property: + +```json title="Result" +{ + "id": "brand_123", + "metadata": { + "category": "home appliances" + } +} +``` + + # Manage Relationships In this chapter, you'll learn how to manage relationships between data models when creating, updating, or retrieving records using the module's main service. @@ -10114,7 +10345,7 @@ export default Post ### json -The `json` method defines a property whose value is a stringified JSON object. +The `json` method defines a property whose value is stored as a stringified JSON object in the database. For example: @@ -10129,6 +10360,8 @@ const Post = model.define("post", { export default Post ``` +Learn more in the [JSON Properties](https://docs.medusajs.com/learn/fundamentals/data-models/json-properties/index.html.md) chapter. + ### array The `array` method defines an array of strings property. @@ -80661,6 +80894,40 @@ Learn more about accepted filters in [this documentation](https://docs.medusajs. The method returns an array of objects of updated records. +*** + +## Update a JSON Property + +```ts +const post = await postModuleService.updatePosts({ + id: "123", + name: "My Post", + metadata: { + category: "news", + tags: ["update", "json"], + }, +}) +``` + +When you have a JSON property in your data model, you can update it by adding, updating, or removing properties within that JSON object. Medusa will merge the properties you pass in the `update` method with the existing JSON object. + +### Remove a Property from the JSON Property + +```ts +const post = await postModuleService.updatePosts({ + id: "123", + metadata: { + is_featured: "", + }, +}) +``` + +To remove a property from the JSON object, you can set its value to an empty string. + +### Learn More about Updating JSON Properties + +Refer to the [JSON Properties](https://docs.medusajs.com/docs/learn/fundamentals/data-models/json-properties/index.html.md) documentation to learn more about how JSON properties work in Medusa and how to update them. + # Service Factory Reference diff --git a/www/apps/book/sidebar.mjs b/www/apps/book/sidebar.mjs index f7d86b56ba..81c8c90cc0 100644 --- a/www/apps/book/sidebar.mjs +++ b/www/apps/book/sidebar.mjs @@ -274,6 +274,11 @@ export const sidebars = [ path: "/learn/fundamentals/data-models/properties", title: "Properties", }, + { + type: "link", + path: "/learn/fundamentals/data-models/json-properties", + title: "JSON Properties", + }, { type: "link", path: "/learn/fundamentals/data-models/relationships", diff --git a/www/apps/resources/app/service-factory-reference/methods/update/page.mdx b/www/apps/resources/app/service-factory-reference/methods/update/page.mdx index 1d6305043d..18b85de1e7 100644 --- a/www/apps/resources/app/service-factory-reference/methods/update/page.mdx +++ b/www/apps/resources/app/service-factory-reference/methods/update/page.mdx @@ -135,3 +135,37 @@ Learn more about accepted filters in [this documentation](../../tips/filtering/p ### Returns The method returns an array of objects of updated records. + +--- + +## Update a JSON Property + +```ts +const post = await postModuleService.updatePosts({ + id: "123", + name: "My Post", + metadata: { + category: "news", + tags: ["update", "json"], + }, +}) +``` + +When you have a JSON property in your data model, you can update it by adding, updating, or removing properties within that JSON object. Medusa will merge the properties you pass in the `update` method with the existing JSON object. + +### Remove a Property from the JSON Property + +```ts +const post = await postModuleService.updatePosts({ + id: "123", + metadata: { + is_featured: "", + }, +}) +``` + +To remove a property from the JSON object, you can set its value to an empty string. + +### Learn More about Updating JSON Properties + +Refer to the [JSON Properties](!docs!/learn/fundamentals/data-models/json-properties) documentation to learn more about how JSON properties work in Medusa and how to update them. diff --git a/www/apps/resources/generated/edit-dates.mjs b/www/apps/resources/generated/edit-dates.mjs index 8d5d360177..deb490ee4c 100644 --- a/www/apps/resources/generated/edit-dates.mjs +++ b/www/apps/resources/generated/edit-dates.mjs @@ -131,7 +131,7 @@ export const generatedEditDates = { "app/service-factory-reference/methods/restore/page.mdx": "2024-07-31T17:01:33+03:00", "app/service-factory-reference/methods/retrieve/page.mdx": "2024-07-31T17:01:33+03:00", "app/service-factory-reference/methods/soft-delete/page.mdx": "2024-07-31T17:01:33+03:00", - "app/service-factory-reference/methods/update/page.mdx": "2024-07-31T17:01:33+03:00", + "app/service-factory-reference/methods/update/page.mdx": "2025-07-31T08:24:03.685Z", "app/service-factory-reference/tips/filtering/page.mdx": "2025-04-23T14:38:29.068Z", "app/service-factory-reference/page.mdx": "2024-07-26T14:40:56+00:00", "app/storefront-development/cart/context/page.mdx": "2025-03-27T14:47:14.258Z", diff --git a/www/apps/resources/generated/generated-commerce-modules-sidebar.mjs b/www/apps/resources/generated/generated-commerce-modules-sidebar.mjs index 53a9074089..584d34fa0c 100644 --- a/www/apps/resources/generated/generated-commerce-modules-sidebar.mjs +++ b/www/apps/resources/generated/generated-commerce-modules-sidebar.mjs @@ -6102,6 +6102,14 @@ const generatedgeneratedCommerceModulesSidebarSidebar = { "path": "https://docs.medusajs.com/resources/how-to-tutorials/tutorials/gift-message", "children": [] }, + { + "loaded": true, + "isPathHref": true, + "type": "ref", + "title": "Generate Invoices", + "path": "https://docs.medusajs.com/resources/how-to-tutorials/tutorials/invoice-generator", + "children": [] + }, { "loaded": true, "isPathHref": true, diff --git a/www/apps/resources/generated/generated-tools-sidebar.mjs b/www/apps/resources/generated/generated-tools-sidebar.mjs index 600c14d321..d912a536b9 100644 --- a/www/apps/resources/generated/generated-tools-sidebar.mjs +++ b/www/apps/resources/generated/generated-tools-sidebar.mjs @@ -819,6 +819,14 @@ const generatedgeneratedToolsSidebarSidebar = { "path": "https://docs.medusajs.com/resources/how-to-tutorials/tutorials/first-purchase-discounts", "children": [] }, + { + "loaded": true, + "isPathHref": true, + "type": "ref", + "title": "Generate Invoices", + "path": "https://docs.medusajs.com/resources/how-to-tutorials/tutorials/invoice-generator", + "children": [] + }, { "loaded": true, "isPathHref": true,