← Back to blog
Merge

How to Merge JSON Configuration Files

Combine base and environment-specific JSON configs without losing nested settings.

2026-02-264 min readUpdated Apr 1, 2026
Example of merging JSON configuration files using a pipeline

Managing JSON config files across environments gets messy quickly. A small override that looks harmless can replace an entire nested object instead of changing just one value.

This shows up all the time in deployment flows, app settings, and automation configs where you have a shared base file plus one environment-specific override.

Problem

You might start with a base config that contains your default settings. Then you add a production file that changes only a few fields, such as the database host, feature flags, or logging level.

The problem is that a shallow merge does not understand nested structure. If the override updates only database.host, you can still lose database.port, database.pool, and the rest of the original database settings.

That kind of mistake is easy to miss and frustrating to debug, especially when the final JSON is headed into a deployment or automation step.

Solution

Forge Json's Deep Merge utility solves this by merging nested objects recursively instead of replacing them at the top level.

Follow this flow:

  1. Load the base JSON as the input document.
  2. Add the environment-specific override as the merge source.
  3. Run the deep merge utility.
  4. Review the output to confirm only the intended fields changed.

The result keeps the original structure while updating only the fields you actually want to override. Nested keys that are not mentioned in the second file stay intact.

_Screenshot placeholder: show the base config, override config, and merged result in the Forge Json UI._

This pattern works especially well for CI/CD pipelines, deployment configs, and any workflow where the final JSON should be assembled from layered inputs without losing important defaults.

Support material

Practical example and product context

Use these examples to understand the transformation and apply the same workflow in your own JSON tasks.

Example Transformation

Base Input
1{
2 "appName": "MyService",
3 "version": "2.1.0",
4 "server": {
5 "host": "0.0.0.0",
6 "port": 3000,
7 "cors": {
8 "enabled": true,
9 "origins": [
10 "http://localhost:3000"
11 ]
12 }
13 },
14 "database": {
15 "host": "localhost",
16 "port": 5432,
17 "name": "myservice_dev",
18 "pool": {
19 "min": 2,
20 "max": 10,
21 "idleTimeout": 30000
22 }
23 },
24 "logging": {
25 "level": "debug",
26 "format": "pretty"
27 },
28 "features": {
29 "darkMode": false,
30 "betaFeatures": false,
31 "analytics": true
32 }
33}
Merge Input
1{
2 "server": {
3 "port": 8080,
4 "cors": {
5 "origins": [
6 "https://myservice.com",
7 "https://admin.myservice.com"
8 ]
9 }
10 },
11 "database": {
12 "host": "db.prod.internal",
13 "name": "myservice_prod",
14 "pool": {
15 "min": 5,
16 "max": 50,
17 "idleTimeout": 10000
18 }
19 },
20 "logging": {
21 "level": "warn",
22 "format": "json",
23 "file": "/var/log/myservice/app.log"
24 },
25 "features": {
26 "darkMode": true
27 }
28}
Config
1{
2 "conflictStrategy": "deepMerge",
3 "arrayStrategy": "replace"
4}
Why this output looks right
  • Values in the Merge Input override matching fields in the Base Input when the same key appears in both documents.
  • Array behavior follows config. In this example, arrayStrategy is replace, so the merge input replaces matching arrays.
Output
1{
2 "appName": "MyService",
3 "version": "2.1.0",
4 "server": {
5 "host": "0.0.0.0",
6 "port": 8080,
7 "cors": {
8 "enabled": true,
9 "origins": [
10 "https://myservice.com",
11 "https://admin.myservice.com"
12 ]
13 }
14 },
15 "database": {
16 "host": "db.prod.internal",
17 "port": 5432,
18 "name": "myservice_prod",
19 "pool": {
20 "min": 5,
21 "max": 50,
22 "idleTimeout": 10000
23 }
24 },
25 "logging": {
26 "level": "warn",
27 "format": "json",
28 "file": "/var/log/myservice/app.log"
29 },
30 "features": {
31 "darkMode": true,
32 "betaFeatures": false,
33 "analytics": true
34 }
35}

Pipeline Example

This is the exact workflow shown in the article.

Merges an environment override into a base config while keeping untouched nested defaults.

Pipeline example from the article

Try this pipeline in the editor

View Utility

Related Articles

Continue with another practical guide in the same workflow area.