1import groovy.json.JsonSlurper
2import groovy.json.JsonOutput
3import java.util.Map
4import java.util.List
5import java.util.HashMap
6import java.util.ArrayList
7
8class JsonTransformer {
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public Map<String, Object> transform(Map<String, Object> sourceJson, Map<String, Object> mappingConfig) {
24if (sourceJson == null || mappingConfig == null) {
25throw new IllegalArgumentException("Source JSON and mapping configuration cannot be null.")
26}
27return transformRecursive(sourceJson, mappingConfig)
28}
29
30private Map<String, Object> transformRecursive(Map<String, Object> source, Map<String, Object> config) {
31Map<String, Object> target = new HashMap<>()
32
33for (Map.Entry<String, Object> entry : config.entrySet()) {
34String targetKey = entry.getKey()
35Object configValue = entry.getValue()
36
37if (configValue instanceof String) {
38String sourceKey = (String) configValue
39if (source.containsKey(sourceKey)) {
40target.put(targetKey, source.get(sourceKey))
41} else {
42
43println "Warning: Source field '${sourceKey}' not found for target key '${targetKey}'."
44}
45} else if (configValue instanceof Map) {
46Map<String, Object> nestedSource = (Map<String, Object>) source.get(targetKey)
47if (nestedSource == null) {
48
49println "Warning: Nested source object for key '${targetKey}' not found. Creating empty target object."
50target.put(targetKey, new HashMap<String, Object>())
51} else {
52target.put(targetKey, transformRecursive(nestedSource, (Map<String, Object>) configValue))
53}
54} else if (configValue instanceof List) {
55
56
57Object sourceArrayObj = source.get(targetKey)
58if (sourceArrayObj instanceof List) {
59List<Object> sourceArray = (List<Object>) sourceArrayObj
60List<Object> transformedArray = new ArrayList<>()
61Map<String, Object> elementConfig = configValue.get(0) instanceof Map ? (Map<String, Object>) configValue.get(0) : null
62
63if (elementConfig != null) {
64for (Object item : sourceArray) {
65if (item instanceof Map) {
66transformedArray.add(transformRecursive((Map<String, Object>) item, elementConfig))
67} else {
68
69transformedArray.add(item)
70}
71}
72target.put(targetKey, transformedArray)
73} else {
74
75println "Warning: Array transformation config missing for key '${targetKey}'. Copying array as-is."
76target.put(targetKey, sourceArray)
77}
78} else {
79
80println "Warning: Expected an array for key '${targetKey}' in source, but found: ${sourceArrayObj.getClass().getName()}."
81}
82} else if (configValue instanceof Closure) {
83Closure customTransform = (Closure) configValue
84
85
86Object result = customTransform.call(source, target)
87if (result != null) {
88
89
90
91
92
93if (result instanceof Map) {
94target.put(targetKey, result)
95} else {
96
97
98
99
100}
101}
102} else {
103
104println "Warning: Unsupported configuration type for key '${targetKey}': ${configValue.getClass().getName()}"
105}
106}
107return target
108}
109
110public static void main(String[] args) {
111JsonTransformer transformer = new JsonTransformer()
112
113
114Map<String, Object> source1 = [
115'userId': 123,
116'userName': 'Alice',
117'emailAddress': 'alice@example.com'
118]
119Map<String, Object> config1 = [
120'id': 'userId',
121'name': 'userName',
122'contactEmail': 'emailAddress'
123]
124Map<String, Object> transformed1 = transformer.transform(source1, config1)
125println "Transformed 1: ${JsonOutput.toJson(transformed1)}"
126
127
128
129Map<String, Object> source2 = [
130'orderId': 'ORD789',
131'customerInfo': [
132'firstName': 'Bob',
133'lastName': 'Smith',
134'address': [
135'street': '123 Main St',
136'city': 'Anytown'
137]
138],
139'items': [
140[
141'productId': 'P101',
142'productName': 'Gadget',
143'quantity': 2,
144'price': 19.99
145],
146[
147'productId': 'P102',
148'productName': 'Widget',
149'quantity': 1,
150'price': 29.99
151]
152]
153]
154Map<String, Object> config2 = [
155'orderReference': 'orderId',
156'customer': [
157'firstName': 'firstName',
158'lastName': 'lastName',
159'location': [
160'street': 'street',
161'city': 'city'
162]
163],
164'products': [ [
165'sku': 'productId',
166'name': 'productName',
167'qty': 'quantity',
168'unitPrice': 'price'
169] ]
170]
171Map<String, Object> transformed2 = transformer.transform(source2, config2)
172println "Transformed 2: ${JsonOutput.toJson(transformed2)}"
173
174
175
176Map<String, Object> source3 = [
177'status': 'ACTIVE',
178'isActive': true,
179'value': 100,
180'secondaryValue': 50
181]
182Map<String, Object> config3 = [
183'currentStatus': 'status',
184'displayValue': { source, target ->
185
186if (source.get('status') == 'ACTIVE' && source.get('isActive')) {
187target.put('displayValue', source.get('value'))
188} else {
189target.put('displayValue', source.get('secondaryValue'))
190}
191}
192]
193Map<String, Object> transformed3 = transformer.transform(source3, config3)
194println "Transformed 3: ${JsonOutput.toJson(transformed3)}"
195
196
197
198Map<String, Object> source4 = [
199'id': 'XYZ',
200'details': [
201'tags': ['A', 'B']
202]
203]
204Map<String, Object> config4 = [
205'reference': 'id',
206'nested': [
207'tags': [ [
208'name': 'tag',
209'value': 'value'
210] ]
211]
212]
213Map<String, Object> transformed4 = transformer.transform(source4, config4)
214println "Transformed 4: ${JsonOutput.toJson(transformed4)}"
215
216
217
218try {
219transformer.transform(null, config1)
220} catch (e) {
221println "Exception 5a: ${e.getMessage()}"
222}
223try {
224transformer.transform(source1, null)
225} catch (e) {
226println "Exception 5b: ${e.getMessage()}"
227}
228Map<String, Object> emptySource = [:]
229Map<String, Object> emptyConfig = [:]
230Map<String, Object> transformed5 = transformer.transform(emptySource, emptyConfig)
231println "Transformed 5 (empty): ${JsonOutput.toJson(transformed5)}"
232}
233}