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		(a, b) => *a = b,
41	};
42}
43
44#[cfg(test)]
45mod tests {
46	use super::*;
47	use serde_json::json;
48
49	#[test]
50	fn test1_simple_merge() {
51		let mut j1 = json!({ "a":123 });
52		merge(&mut j1, json!({ "b":256 }));
53		assert_eq!(j1, json!({ "a":123, "b":256 }));
54	}
55
56	#[test]
57	fn test2_patch_simple_merge_nested() {
58		let mut j1 = json!({
59			"a": {
60				"name": "xxx",
61				"value": 123
62			},
63			"b": { "c" : { "inner_name": "yyy" } }
64		});
65
66		let j2 = json!({
67			"a": {
68				"keys": ["a", "b", "c" ]
69			}
70		});
71
72		merge(&mut j1, j2);
73		assert_eq!(
74			j1,
75			json!({"a":{"keys":["a","b","c"],"name":"xxx","value":123}, "b": { "c" : { "inner_name": "yyy" } }})
76		);
77	}
78
79	#[test]
80	fn test3_patch_overrides_existing_keys() {
81		let mut j1 = json!({
82			"a": {
83				"name": "xxx",
84				"value": 123,
85				"keys": ["d"]
86
87			}
88		});
89
90		let j2 = json!({
91			"a": {
92				"keys": ["a", "b", "c" ]
93			}
94		});
95
96		merge(&mut j1, j2);
97		assert_eq!(j1, json!({"a":{"keys":["a","b","c"],"name":"xxx","value":123}}));
98	}
99
100	#[test]
101	fn test4_patch_overrides_existing_keys() {
102		let mut j1 = json!({
103			"a": {
104				"name": "xxx",
105				"value": 123,
106				"b" : {
107					"inner_name": "yyy"
108				}
109			}
110		});
111
112		let j2 = json!({
113			"a": {
114				"name": "new_name",
115				"b" : {
116					"inner_name": "inner_new_name"
117				}
118			}
119		});
120
121		merge(&mut j1, j2);
122		assert_eq!(
123			j1,
124			json!({ "a": {"name":"new_name", "value":123, "b" : { "inner_name": "inner_new_name" }} })
125		);
126	}
127
128	#[test]
129	fn test5_patch_overrides_existing_nested_keys() {
130		let mut j1 = json!({
131			"a": {
132				"name": "xxx",
133				"value": 123,
134				"b": {
135					"c": {
136						"d": {
137							"name": "yyy",
138							"value": 256
139						}
140					}
141				}
142			},
143		});
144
145		let j2 = json!({
146			"a": {
147				"value": 456,
148				"b": {
149					"c": {
150						"d": {
151							"name": "new_name"
152						}
153					}
154				}
155			}
156		});
157
158		merge(&mut j1, j2);
159		assert_eq!(
160			j1,
161			json!({ "a": {"name":"xxx", "value":456, "b": { "c": { "d": { "name": "new_name", "value": 256 }}}}})
162		);
163	}
164
165	#[test]
166	fn test6_patch_does_not_remove_keys_if_null() {
167		let mut j1 = json!({
168			"a": {
169				"name": "xxx",
170				"value": 123,
171				"enum_variant_1": {
172					"name": "yyy",
173				}
174			},
175		});
176
177		let j2 = json!({
178			"a": {
179				"value": 456,
180				"enum_variant_1": null,
181				"enum_variant_2": 32,
182			}
183		});
184
185		merge(&mut j1, j2);
186		assert_eq!(
187			j1,
188			json!({
189				"a": {
190					"name":"xxx",
191					"value":456,
192					"enum_variant_1": null,
193					"enum_variant_2": 32
194				}
195			})
196		);
197	}
198}