blob: 96ff8cacd08e8afeed11fd42e4dbe276dc5fd3d5 [file] [log] [blame]
Jooyung Han04329f12019-08-01 23:35:08 +09001#!/usr/bin/env python
2#
3# Copyright (C) 2019 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17
18import argparse
19import collections
20import json
21import sys
22
23def follow_path(obj, path):
24 cur = obj
25 last_key = None
26 for key in path.split('.'):
27 if last_key:
28 if last_key not in cur:
29 return None,None
30 cur = cur[last_key]
31 last_key = key
32 if last_key not in cur:
33 return None,None
34 return cur, last_key
35
36
37def ensure_path(obj, path):
38 cur = obj
39 last_key = None
40 for key in path.split('.'):
41 if last_key:
42 if last_key not in cur:
43 cur[last_key] = dict()
44 cur = cur[last_key]
45 last_key = key
46 return cur, last_key
47
48
49class SetValue(str):
50 def apply(self, obj, val):
51 cur, key = ensure_path(obj, self)
52 cur[key] = val
53
54
55class Replace(str):
56 def apply(self, obj, val):
57 cur, key = follow_path(obj, self)
58 if cur:
59 cur[key] = val
60
61
Alexei Nicoara7d69b1d2022-07-11 12:38:50 +010062class ReplaceIfEqual(str):
63 def apply(self, obj, old_val, new_val):
64 cur, key = follow_path(obj, self)
65 if cur and cur[key] == int(old_val):
66 cur[key] = new_val
67
68
Jooyung Han04329f12019-08-01 23:35:08 +090069class Remove(str):
70 def apply(self, obj):
71 cur, key = follow_path(obj, self)
72 if cur:
73 del cur[key]
74
75
76class AppendList(str):
77 def apply(self, obj, *args):
78 cur, key = ensure_path(obj, self)
79 if key not in cur:
80 cur[key] = list()
81 if not isinstance(cur[key], list):
82 raise ValueError(self + " should be a array.")
83 cur[key].extend(args)
84
85
86def main():
87 parser = argparse.ArgumentParser()
88 parser.add_argument('-o', '--out',
89 help='write result to a file. If omitted, print to stdout',
90 metavar='output',
91 action='store')
92 parser.add_argument('input', nargs='?', help='JSON file')
93 parser.add_argument("-v", "--value", type=SetValue,
94 help='set value of the key specified by path. If path doesn\'t exist, creates new one.',
95 metavar=('path', 'value'),
96 nargs=2, dest='patch', default=[], action='append')
97 parser.add_argument("-s", "--replace", type=Replace,
98 help='replace value of the key specified by path. If path doesn\'t exist, no op.',
99 metavar=('path', 'value'),
100 nargs=2, dest='patch', action='append')
Alexei Nicoara7d69b1d2022-07-11 12:38:50 +0100101 parser.add_argument("-se", "--replace-if-equal", type=ReplaceIfEqual,
102 help='replace value of the key specified by path to new_value if it\'s equal to old_value.' +
103 'If path doesn\'t exist or the value is not equal to old_value, no op.',
104 metavar=('path', 'old_value', 'new_value'),
105 nargs=3, dest='patch', action='append')
Jooyung Han04329f12019-08-01 23:35:08 +0900106 parser.add_argument("-r", "--remove", type=Remove,
107 help='remove the key specified by path. If path doesn\'t exist, no op.',
108 metavar='path',
109 nargs=1, dest='patch', action='append')
110 parser.add_argument("-a", "--append_list", type=AppendList,
111 help='append values to the list specified by path. If path doesn\'t exist, creates new list for it.',
112 metavar=('path', 'value'),
113 nargs='+', dest='patch', default=[], action='append')
114 args = parser.parse_args()
115
116 if args.input:
117 with open(args.input) as f:
118 obj = json.load(f, object_pairs_hook=collections.OrderedDict)
119 else:
120 obj = json.load(sys.stdin, object_pairs_hook=collections.OrderedDict)
121
122 for p in args.patch:
123 p[0].apply(obj, *p[1:])
124
125 if args.out:
126 with open(args.out, "w") as f:
Martin Stjernholm37fa32c2020-02-24 15:52:31 +0000127 json.dump(obj, f, indent=2, separators=(',', ': '))
128 f.write('\n')
Jooyung Han04329f12019-08-01 23:35:08 +0900129 else:
Martin Stjernholm37fa32c2020-02-24 15:52:31 +0000130 print(json.dumps(obj, indent=2, separators=(',', ': ')))
Jooyung Han04329f12019-08-01 23:35:08 +0900131
132
133if __name__ == '__main__':
134 main()