npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

json_merger

v1.2.0

Published

Merge JSON with indicators such as @override, @match, @delete and @insert to tell the processor how to merge the files.

Downloads

1,754

Readme

json_merger downloads/month json_merger version json_merger license

Table of Contents:

Apply indicators such as @insert, @match and @override to tell the processor how to merge the files.

.fromFile('file.json')

var json_merger = require('json_merger');
var result = json_merger.fromFile('fileA.json');

fileA.json:

{
	"@extends": "fileB.json",
	"prop1": {
		"@override": true,
		"prop_a": "this will override fileB.json's property prop1"
	},
	"prop2": {
		"prop_a": "some value"
	}
}

fileB.json:

{
	"prop1": {
		"prop_b": "never gonna be seen"
	},
	"prop2": {
		"prop_b": "some other value"
	}
}

Result:

{
	"prop1": {
		"prop_a": "this will override fileB.json's property prop1"
	},
	"prop2": {
		"prop_a": "some value",
		"prop_b": "some other value"
	}
}

.fromObject(object)

var json_merger = require('json_merger');

var objA = {
	"@extends": "fileB.json",
		"prop1": {
			"@override": true,
			"prop_a": "this will override fileB.json's property prop1"
	},
		"prop2": {
		"prop_a": "some value"
	}
};

var result = json_merger.fromObject(objA);

fileB.json:

{
	"prop1": {
		"prop_b": "never gonna be seen"
	},
	"prop2": {
		"prop_b": "some other value"
	}
}

Result:

{
	"prop1": {
		"prop_a": "this will override fileB.json's property prop1"
	},
	"prop2": {
		"prop_a": "some value",
		"prop_b": "some other value"
	}
}

config

{
    asText: false, // true, false, 'pretty'
    javascript: false, // true, false
    scope: '', // directory to look for initial file
    variables: {
        // contains a key->value object with variables to @extends
    }
}

config.asText

default: false (in command line interface it will default to true)

Values are true, false, pretty where pretty will indent the JSON with \t for each block.

config.javascript

Expiremental

default: false

Preserve JavaScript functions, regexp, etc see Expiremental usage

config.scope

default: process.cwd()

The initial directory which the inputFile is relative too, will be overridden for each @extends file and is set to dirname of current inputFile.

config.variables

default: {}

Variables is used in @extends like the following:

json_merger.fromFile('fileA.json', {
    "project_root": "/var/www/project123"
});

fileA.json

{
    "@extends": ["${project_root}/fileB.json"]
}

Indicators:

@extends

An array / string indicating which files a given object extends, this is a root indicator

{
    "@extends": ["main_file.json", "project_file.js", "mixin_file.json"]
}

@override

An array or true indicating that the given property will be overridden. When used with true the whole property will be overridden. When used with an array the listed properties will be overridden:

Usage of true

{
	"@extends": ["b.json"],
	"a": {
		"@override": true,
		"prop_1": {"a":1},
		"prop_2": {"a":2}
	}
}

b.json

{
	"a": {
		"prop_1": {"b":1},
		"prop_2": {"b":2},
		"prop_3": {"b":3},
		"prop_4": {"b":4}
	}
}

Result

{
	"a": {
		"prop_1": {"a":1},
		"prop_2": {"a":2}
	}
}

Usage of array

{
	"@extends": ["b.json"],
	"a": {
		"@override": ["prop_1"],
		"prop_1": {"a":1},
		"prop_2": {"a":2}
	}
}

b.json

{
	"a": {
		"prop_1": {"b":1},
		"prop_2": {"b":2},
		"prop_3": {"b":3},
		"prop_4": {"b":4}
	}
}

Result

{
	"a": {
		"prop_1": {"a":1},
		"prop_2": {"a":2, "b":2},
		"prop_3": {"b":3},
		"prop_4": {"b":4}
	}
}

@append, @prepend, @insert

When working with array the default behaviour will be to merge on indexes, eg first item in the arrays will be merged together etc.

  • @append: true is alias for @insert: -1
  • @prepend: true is alias for @insert: 0

Using @insert:

{
	"@extends": ["b.json"],
	"a": [
		{
			"@insert": 1,
			"a": 1
		}
	]
}

b.json

{
	"a": [
		{
			"b": 1
		},
		{
			"b": 2
		},
		{
			"b": 3
		}
	]
}

Result

{
	"a": [
		{
			"b": 1
		},
		{
			"a": 1
		},
		{
			"b": 2
		},
		{
			"b": 3
		}
	]
}

@match

Match can be used to match a given item in an array; Supported syntax:

[prop1=val1][prop2='val2']

You can ether use prop1, prop2 for matching regular properties @value which will match the value of primitives in the array:

Quoting is optional but required if you want strict comparison, eg [prop='2'] will match {"prop": "2"} and not {"prop": 2}

Usage

{
	"@extends": ["b.json"],
	"columns": [
		{
			"@match": "[name=token]",
			"type": "float"
		}
	]
}

b.json

{
	"columns": [
		{
			"name": "firstname",
			"type": "varchar(64)"
		},
		{
			"name": "lastname",
			"type": "varchar(64)"
		},
		{
			"name": "token",
			"type": "integer"
		}
	]
}

Result

{
	"columns": [
		{
			"name": "firstname",
			"type": "varchar(64)"
		},
		{
			"name": "lastname",
			"type": "varchar(64)"
		},
		{
			"name": "token",
			"type": "float"
		}
	]
}

Advanced usage

{
    "@extends": ["b.json"],
    "outer_array": [
        {
            "@match": "[key=value]/inner_array/[inner_key=inner_value]",
            "type": "float"
        }
    ]
}

b.json

{
    "outer_array": [
        {
            "key": "value",
            "inner_array": [
                {
                    "inner_key": "inner_value"
                }
            ]
        }
    ]
}

Result

{
    "outer_array": [
        {
            "key": "value",
            "inner_array": [
                {
                    "inner_key": "inner_value",
                    "type": "float"
                }
            ]
        }
    ]
}

Advanced Usage 2 (@value)

{
	"@extends": ["b.json"],
	"seq": [
		{
			"@match": "[@value=b]",
			"@delete": true
		}
	]
}

b.json

{
	"seq": [
		"a",
		"b",
		"c",
		"d"
	]
}

Result

{
	"columns": [
		"a",
		"c",
		"d"
	]
}

@move

This indicator is the same as @insert but is used together with @match.

@value

Used when merging arrays containing primitives or other arrays

{
    "@extends": ["fileB.json"],
	"sequence": [
		{
			"@insert": 1,
			"@value": "insertedField"
		}
	]
}

fileB.json

{
	"sequence": [
		"fieldA",
		"fieldB",
		"fieldC"
	]
}

Output

{
	"sequence": [
		"fieldA",
		"insertedField",
		"fieldB",
		"fieldC"
	]
}

@comment

These will be removed in the merging process and is intented to be used for internal comments about overrides etc.

{
    "@comment": "I did this because...."
}

@id

This can be matches in @match using the following syntax:

{
	"@extends": ["b.json"],
    "array": [
		{ "a": 2, "@match": "[@id=my_id]" }
    ]
}

b.json

{
    "array": [
		{ "a": 1 },
		{ "a": 2, "@id": "my_id" }
    ]
}

.merge(objA, objB)

You can use json_merger without having to use JSON stored in files, you can use it directly with JavaScript objects:

var json_merger = require('json_merger');

var a = {
    a: {
        "@override": true,
        "my_value": 1234
    }
};
var b = {
    a: {
        "my_b_value": 1234
    }
}

var result = json_merger.merge(a, b);

console.log(result.a.my_value); // 1234
console.log(result.a.my_b_value); // undefined

Command line interface json_merger

You can use json_merger as a command line tool:

Usage: json_merger <file> [OPTIONS]

Mandatory arguments to long options are mandatory for short options too.

  -p, --pretty            Prettify the output json
  -j, --javascript        Perserve JavaScript functions, regex, etc...
  -v, --variables         Send key=value list of variables
                            Usage -v key1=value1 -v key2=value2

  -h, --help              Show this help
  -v, --version           Show the version

Usage:

json_merger input.json > out.json
json_merger input.json --pretty > out.json
json_merger input.json --javascript > out.json
json_merger input.json -p -j -v "root=/var/www/" > out.json

Make sure that add json_merger to the $PATH variable.

npm install -g json_merger

Experimental Usage:

Working with JavaScript code in JSON Use at own risk :-)

var json_merger = require('json_merger');

var output = json_merger.fromFile('file.jsonx', {
    asText: 'pretty',
    javascript: true
});

file.jsonx

{
    "@extends": ["fileB.jsonx"],
    "my_function": function(a, b) { return doStuff(a, b) },
    "obj": {
        "a": (function(a, b) { /* code here */ })(1, 2)
    }
}

fileB.jsonx

{
    "@extends": ["fileB.jsonx"],
    "obj": {
        "b": (function(a, b) { /* another code here */ })(1, 2)
    }
}

Result:

{
    "my_function": function(a, b) { return doStuff(a, b) },
    "obj": {
        "a": (function(a, b) { /* code here */ })(1, 2),
        "b": (function(a, b) { /* another code here */ })(1, 2)
    }
}

Root indicators

Root indicators is properties that are only supported on the outer most level of the JSON tree.

Current supported root indicators:

License:

The MIT License (MIT)

Copyright (c) 2015 Andreas Louv

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+++++ +++++ +[>+++++ +++++<-]>----.+++++++++.----.-.---------------.++++++++++++++.--------.+++++++++++++.-----------.--.+++++++++++++.