referrerpolicy=no-referrer-when-downgrade

sc_chain_spec/
json_patch.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! A helper module providing json patching functions.
20
21use serde_json::Value;
22
23/// Recursively merges two JSON objects, `a` and `b`, into a single object.
24///
25/// If a key exists in both objects, the value from `b` will override the value from `a` (also if
26/// value in `b` is `null`).
27/// If a key exists only in `b` and not in `a`, it will be added to `a`.
28/// No keys will be removed from `a`.
29///
30/// # Arguments
31///
32/// * `a` - A mutable reference to the target JSON object to merge into.
33/// * `b` - The JSON object to merge with `a`.
34pub fn merge(a: &mut Value, b: Value) {
35	match (a, b) {
36		(Value::Object(a), Value::Object(b)) => {
37			for (k, v) in b {
38				merge(a.entry(k).or_insert(Value::Null), v);
39			}
40		},
41		(a, b) => *a = b,
42	};
43}
44
45#[cfg(test)]
46mod tests {
47	use super::*;
48	use serde_json::json;
49
50	#[test]
51	fn test1_simple_merge() {
52		let mut j1 = json!({ "a":123 });
53		merge(&mut j1, json!({ "b":256 }));
54		assert_eq!(j1, json!({ "a":123, "b":256 }));
55	}
56
57	#[test]
58	fn test2_patch_simple_merge_nested() {
59		let mut j1 = json!({
60			"a": {
61				"name": "xxx",
62				"value": 123
63			},
64			"b": { "c" : { "inner_name": "yyy" } }
65		});
66
67		let j2 = json!({
68			"a": {
69				"keys": ["a", "b", "c" ]
70			}
71		});
72
73		merge(&mut j1, j2);
74		assert_eq!(
75			j1,
76			json!({"a":{"keys":["a","b","c"],"name":"xxx","value":123}, "b": { "c" : { "inner_name": "yyy" } }})
77		);
78	}
79
80	#[test]
81	fn test3_patch_overrides_existing_keys() {
82		let mut j1 = json!({
83			"a": {
84				"name": "xxx",
85				"value": 123,
86				"keys": ["d"]
87
88			}
89		});
90
91		let j2 = json!({
92			"a": {
93				"keys": ["a", "b", "c" ]
94			}
95		});
96
97		merge(&mut j1, j2);
98		assert_eq!(j1, json!({"a":{"keys":["a","b","c"],"name":"xxx","value":123}}));
99	}
100
101	#[test]
102	fn test4_patch_overrides_existing_keys() {
103		let mut j1 = json!({
104			"a": {
105				"name": "xxx",
106				"value": 123,
107				"b" : {
108					"inner_name": "yyy"
109				}
110			}
111		});
112
113		let j2 = json!({
114			"a": {
115				"name": "new_name",
116				"b" : {
117					"inner_name": "inner_new_name"
118				}
119			}
120		});
121
122		merge(&mut j1, j2);
123		assert_eq!(
124			j1,
125			json!({ "a": {"name":"new_name", "value":123, "b" : { "inner_name": "inner_new_name" }} })
126		);
127	}
128
129	#[test]
130	fn test5_patch_overrides_existing_nested_keys() {
131		let mut j1 = json!({
132			"a": {
133				"name": "xxx",
134				"value": 123,
135				"b": {
136					"c": {
137						"d": {
138							"name": "yyy",
139							"value": 256
140						}
141					}
142				}
143			},
144		});
145
146		let j2 = json!({
147			"a": {
148				"value": 456,
149				"b": {
150					"c": {
151						"d": {
152							"name": "new_name"
153						}
154					}
155				}
156			}
157		});
158
159		merge(&mut j1, j2);
160		assert_eq!(
161			j1,
162			json!({ "a": {"name":"xxx", "value":456, "b": { "c": { "d": { "name": "new_name", "value": 256 }}}}})
163		);
164	}
165
166	#[test]
167	fn test6_patch_does_not_remove_keys_if_null() {
168		let mut j1 = json!({
169			"a": {
170				"name": "xxx",
171				"value": 123,
172				"enum_variant_1": {
173					"name": "yyy",
174				}
175			},
176		});
177
178		let j2 = json!({
179			"a": {
180				"value": 456,
181				"enum_variant_1": null,
182				"enum_variant_2": 32,
183			}
184		});
185
186		merge(&mut j1, j2);
187		assert_eq!(
188			j1,
189			json!({
190				"a": {
191					"name":"xxx",
192					"value":456,
193					"enum_variant_1": null,
194					"enum_variant_2": 32
195				}
196			})
197		);
198	}
199}