2 * ============LICENSE_START=======================================================
\r
4 * ================================================================================
\r
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
\r
6 * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
\r
7 * ================================================================================
\r
8 * Licensed under the Apache License, Version 2.0 (the "License");
\r
9 * you may not use this file except in compliance with the License.
\r
10 * You may obtain a copy of the License at
\r
12 * http://www.apache.org/licenses/LICENSE-2.0
\r
14 * Unless required by applicable law or agreed to in writing, software
\r
15 * distributed under the License is distributed on an "AS IS" BASIS,
\r
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
17 * See the License for the specific language governing permissions and
\r
18 * limitations under the License.
\r
19 * ============LICENSE_END=========================================================
\r
22 package org.openecomp.mso.bpmn.core.json;
\r
24 import java.io.IOException;
\r
25 import java.util.ArrayList;
\r
26 import java.util.HashMap;
\r
27 import java.util.Iterator;
\r
28 import java.util.List;
\r
29 import java.util.Map;
\r
30 import java.util.StringTokenizer;
\r
32 import org.camunda.bpm.engine.delegate.DelegateExecution;
\r
33 import org.camunda.bpm.engine.runtime.Execution;
\r
34 import org.json.JSONArray;
\r
35 import org.json.JSONException;
\r
36 import org.json.JSONObject;
\r
37 import org.json.XML;
\r
38 import org.openecomp.mso.apihandler.common.ValidationException;
\r
39 //import org.openecomp.mso.bpmn.core.BPMNLogger;
\r
40 import org.openecomp.mso.bpmn.core.xml.XmlTool;
\r
41 import org.openecomp.mso.logger.MsoLogger;
\r
43 import com.fasterxml.jackson.databind.JsonNode;
\r
44 import com.github.fge.jackson.JsonLoader;
\r
45 import com.github.fge.jsonschema.core.exceptions.ProcessingException;
\r
46 import com.github.fge.jsonschema.core.report.ProcessingReport;
\r
47 import com.github.fge.jsonschema.main.JsonSchemaFactory;
\r
48 import com.github.fge.jsonschema.main.JsonValidator;
\r
51 * Utility class for JSON processing
\r
55 * Note: It was observed, that depending on the JSON implementation, an org.json.JSONException or a
\r
56 * java.util.NoSuchElementException will be thrown in the event of the key value being "not found"
\r
57 * in a JSON document. A general check has been added to the applicable catch blocks for this
\r
58 * this type of behavior to reduce the amount of logging. As a key value not being found is
\r
59 * expect behavior, it makes no sense to log the stack trace associated with this type of failure.
\r
62 public class JsonUtils {
\r
64 private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL);
\r
65 private static int MSOJsonIndentFactor = 3;
\r
68 * Uses the JSONObject static method to convert a XML doc to JSON.
\r
70 * @param xml String containing the XML doc
\r
71 * @param pretty flag to determine if the output should be formatted
\r
72 * @return String containing the JSON translation
\r
74 public static String xml2json(String xml, Boolean pretty) {
\r
75 // String isDebugLogEnabled = "true";
\r
77 // name spaces cause problems, so just remove them
\r
78 JSONObject jsonObj = XML.toJSONObject(XmlTool.removeNamespaces(xml));
\r
80 return jsonObj.toString();
\r
82 // add an indent to make it 'pretty'
\r
83 return jsonObj.toString(MSOJsonIndentFactor);
\r
85 } catch (Exception e){
\r
86 msoLogger.debug("xml2json(): unable to parse xml and convert to json. Exception was: " + e.toString(), e);
\r
92 * Invokes xml2json(String, Boolean) defaulting to 'pretty' output.
\r
94 * @param xml String containing the XML doc
\r
95 * @return String containing the JSON translation
\r
97 public static String xml2json(String xml) {
\r
98 return xml2json(xml, true);
\r
102 * Uses the JSONObject static method to convert a JSON doc to XML.
\r
103 * Note: this method may not generate valid XML if the JSONObject
\r
104 * contains JSONArrays which are used to represent XML attributes
\r
107 * @param jsonStr String containing the JSON doc
\r
108 * @param pretty flag to determine if the output should be formatted
\r
109 * @return String containing the XML translation
\r
111 public static String json2xml(String jsonStr, Boolean pretty) {
\r
112 // String isDebugLogEnabled = "true";
\r
114 JSONObject jsonObj = new JSONObject(jsonStr);
\r
116 // return XmlTool.normalize(XML.toString(jsonObj));
\r
117 // use the local class method which properly handles certain JSONArray content
\r
118 return XmlTool.normalize(toXMLString(jsonObj, null));
\r
120 // return XML.toString(jsonObj);
\r
121 // use the local class method which properly handles certain JSONArray content
\r
122 return toXMLString(jsonObj, null);
\r
124 } catch (Exception e){
\r
125 msoLogger.debug("json2xml(): unable to parse json and convert to xml. Exception was: " + e.toString(), e);
\r
131 * Uses a modified version of the org.json.XML toString() algorithm
\r
132 * to convert a JSONObject to an XML Doc. The intent of this is to
\r
133 * correctly generate XML from JSON including TAGs for JSONArrays
\r
135 * @param obj org.json.JSON object to be converted to XML
\r
136 * @param tagName optional XML tagname supplied primarily during recursive calls
\r
137 * @return String containing the XML translation
\r
139 public static String toXMLString(Object obj, String tagName) throws JSONException {
\r
140 StringBuilder strBuf = new StringBuilder();
\r
143 JSONObject jsonObj;
\r
145 Iterator<String> keys;
\r
149 if (obj instanceof JSONObject) {
\r
150 // msoLogger.debug("toXMLString(): is a JSONObject");
\r
151 // append "<tagName>" to the XML output
\r
152 if (tagName != null) {
\r
153 // msoLogger.debug("toXMLString(): adding opening tagName: " + tagName);
\r
154 strBuf.append("<");
\r
155 strBuf.append(tagName);
\r
156 strBuf.append(">");
\r
158 // iterate thru the keys.
\r
159 jsonObj = (JSONObject) obj;
\r
160 keys = jsonObj.keys();
\r
161 while (keys.hasNext()) {
\r
163 // msoLogger.debug("toXMLString(): key is " + k);
\r
164 curObj = jsonObj.opt(key);
\r
165 if (curObj == null) {
\r
168 if (curObj instanceof String) {
\r
169 str = (String) curObj;
\r
173 // append the content to the XML output
\r
174 if ("content".equals(key)) {
\r
175 if (curObj instanceof JSONArray) {
\r
176 jsonArr = (JSONArray) curObj;
\r
177 len = jsonArr.length();
\r
178 for (i = 0; i < len; i += 1) {
\r
180 strBuf.append('\n');
\r
182 strBuf.append(XML.escape(jsonArr.get(i).toString()));
\r
185 strBuf.append(XML.escape(curObj.toString()));
\r
187 // append an array of similar keys to the XML output
\r
188 } else if (curObj instanceof JSONArray) {
\r
189 jsonArr = (JSONArray) curObj;
\r
190 len = jsonArr.length();
\r
191 // msoLogger.debug("toXMLString(): found JSONArray: " + key + ", size: " + len);
\r
192 for (i = 0; i < len; i += 1) {
\r
193 curObj = jsonArr.get(i);
\r
194 if (curObj instanceof JSONArray) {
\r
195 // The XML tags for the nested array should be generated below when this method
\r
196 // is called recursively and the JSONArray object is passed
\r
197 // strBuf.append("<");
\r
198 // strBuf.append(key);
\r
199 // strBuf.append(">");
\r
200 strBuf.append(toXMLString(curObj, null));
\r
201 // strBuf.append("</");
\r
202 // strBuf.append(key);
\r
203 // strBuf.append(">");
\r
205 // msoLogger.debug("toXMLString(): recursive call toXML() with tagName null");
\r
206 // append the opening tag for the array (before 1st element)
\r
208 strBuf.append("<");
\r
209 strBuf.append(key);
\r
210 strBuf.append(">");
\r
212 // append the opening tag for the array
\r
213 strBuf.append(toXMLString(curObj, null));
\r
214 // append the closing tag for the array (after last element)
\r
215 if (i == (len - 1)) {
\r
216 strBuf.append("</");
\r
217 strBuf.append(key);
\r
218 strBuf.append(">");
\r
222 } else if (curObj.equals("")) {
\r
223 // append a closing tag "<key>" to the XML output
\r
224 strBuf.append("<");
\r
225 strBuf.append(key);
\r
226 strBuf.append("/>");
\r
228 // msoLogger.debug("toXMLString(): recursive call toXMLString() with tagName: " + key);
\r
229 strBuf.append(toXMLString(curObj, key));
\r
231 // msoLogger.debug("toXML(): partial XML: " + strBuf.toString());
\r
233 if (tagName != null) {
\r
234 // append the closing tag "</tagName>" to the XML output
\r
235 // msoLogger.debug("toXMLString(): adding closing tagName: " + tagName);
\r
236 strBuf.append("</");
\r
237 strBuf.append(tagName);
\r
238 strBuf.append(">");
\r
240 return strBuf.toString();
\r
241 // XML does not have good support for arrays. If an array appears in a place
\r
242 // where XML is lacking, synthesize an < array > element.
\r
243 } else if (obj instanceof JSONArray) {
\r
244 jsonArr = (JSONArray) obj;
\r
245 len = jsonArr.length();
\r
246 for (i = 0; i < len; ++i) {
\r
247 curObj = jsonArr.opt(i);
\r
248 strBuf.append(toXMLString(curObj, (tagName == null) ? "array"
\r
251 return strBuf.toString();
\r
253 // msoLogger.debug("toXML(): in else block with tagName: " + tagName);
\r
254 str = (obj == null) ? "null" : XML.escape(obj.toString());
\r
255 return (tagName == null) ? "\"" + str + "\""
\r
256 : (str.length() == 0) ? "<" + tagName + "/>" : "<"
\r
257 + tagName + ">" + str + "</" + tagName + ">";
\r
262 * Invokes json2xml(String, Boolean) defaulting to 'pretty' output.
\r
264 * @param jsonStr String containing the XML doc
\r
265 * @return String containing the JSON translation
\r
267 public static String json2xml(String jsonStr) {
\r
268 return json2xml(jsonStr, true);
\r
272 * Formats the JSON String using the value of MSOJsonIndentFactor.
\r
274 * @param jsonStr String containing the JSON doc
\r
275 * @return String containing the formatted JSON doc
\r
277 public static String prettyJson(String jsonStr) {
\r
278 // String isDebugLogEnabled = "true";
\r
280 JSONObject jsonObj = new JSONObject(jsonStr);
\r
281 return jsonObj.toString(MSOJsonIndentFactor);
\r
282 } catch (Exception e){
\r
283 msoLogger.debug("prettyJson(): unable to parse/format json input. Exception was: " + e.toString(), e);
\r
289 * Returns an Iterator over the JSON keys in the specified JSON doc.
\r
291 * @param jsonStr String containing the JSON doc
\r
292 * @return Iterator over the JSON keys
\r
293 * @throws JSONException if the doc cannot be parsed
\r
295 public static Iterator <String> getJsonIterator(String jsonStr) throws JSONException {
\r
296 return new JSONObject(jsonStr).keys();
\r
300 * Returns the name of the "root" property in the specified JSON doc. The
\r
301 * "root" property is the single top-level property in the JSON doc. An
\r
302 * exception is thrown if the doc is empty or if it contains more than one
\r
303 * top-level property.
\r
305 * @param jsonStr String containing the JSON doc
\r
306 * @return the name of the "root" property
\r
307 * @throws JSONException if the doc cannot be parsed, or if it is empty, or if
\r
308 * it contains more than one top-level property
\r
310 public static String getJsonRootProperty(String jsonStr) throws JSONException {
\r
311 Iterator<String> iter = getJsonIterator(jsonStr);
\r
313 if (!iter.hasNext()) {
\r
314 throw new JSONException("Empty JSON object");
\r
317 String rootPropertyName = iter.next();
\r
319 if (iter.hasNext()) {
\r
320 throw new JSONException("JSON object has more than one root property");
\r
323 return rootPropertyName;
\r
327 * Invokes the getJsonRawValue() method and returns the String equivalent of
\r
328 * the object returned.
\r
330 * TBD: May need separate methods for boolean, float, and integer fields if the
\r
331 * String representation is not sufficient to meet client needs.
\r
333 * @param jsonStr String containing the JSON doc
\r
334 * @param keys full key path to the target value in the format of "key1.key2.key3..."
\r
335 * @return String field value associated with keys
\r
337 public static String getJsonValue(String jsonStr, String keys) {
\r
338 // String isDebugLogEnabled = "true";
\r
340 Object rawValue = getJsonRawValue(jsonStr, keys);
\r
341 if (rawValue == null) {
\r
344 if (rawValue instanceof String) {
\r
345 msoLogger.debug("getJsonValue(): the raw value is a String Object=" + rawValue);
\r
346 return (String) rawValue;
\r
348 msoLogger.debug("getJsonValue(): the raw value is NOT a String Object=" + rawValue.toString());
\r
349 return rawValue.toString();
\r
352 } catch (Exception e) {
\r
353 msoLogger.debug("getJsonValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString(),e);
\r
359 * Invokes the getJsonRawValue() method with the wrap flag set to true
\r
360 * and returns the String equivalent of the json node object returned.
\r
362 * @param jsonStr String containing the JSON doc
\r
363 * @param keys full key path to the target value in the format of "key1.key2.key3..."
\r
364 * @return String field value associated with keys
\r
366 public static String getJsonNodeValue(String jsonStr, String keys) {
\r
367 // String isDebugLogEnabled = "true";
\r
369 Object rawValue = getJsonRawValue(jsonStr, keys, true);
\r
370 if (rawValue == null) {
\r
373 if (rawValue instanceof String) {
\r
374 msoLogger.debug("getJsonNodeValue(): the raw value is a String Object=" + rawValue);
\r
375 return (String) rawValue;
\r
377 msoLogger.debug("getJsonNodeValue(): the raw value is NOT a String Object=" + rawValue.toString());
\r
378 return rawValue.toString();
\r
381 } catch (Exception e) {
\r
382 msoLogger.debug("getJsonNodeValue(): unable to parse json to retrieve node for field=" + keys + ". Exception was: " + e.toString(), e);
\r
388 * Invokes the getJsonRawValue() method and returns the String equivalent of
\r
389 * the object returned.
\r
391 * TBD: May need separate methods for boolean, float, and integer fields if the
\r
392 * String representation is not sufficient to meet client needs.
\r
394 * @param jsonStr String containing the JSON doc
\r
395 * @param keys full key path to the target value in the format of "key1.key2.key3..."
\r
396 * @return String field value associated with keys
\r
398 public static int getJsonIntValue(String jsonStr, String keys) {
\r
399 // String isDebugLogEnabled = "true";
\r
401 Object rawValue = getJsonRawValue(jsonStr, keys);
\r
402 if (rawValue == null) {
\r
405 if (rawValue instanceof Integer) {
\r
406 msoLogger.debug("getJsonValue(): the raw value is an Integer Object=" + rawValue);
\r
407 return (Integer) rawValue;
\r
409 msoLogger.debug("getJsonIntValue(): the raw value is NOT an Integer Object=" + rawValue.toString());
\r
413 } catch (Exception e) {
\r
414 msoLogger.debug("getJsonIntValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString(), e);
\r
420 * Invokes the getJsonRawValue() method and returns the boolean equivalent of
\r
421 * the object returned.
\r
423 * @param jsonStr String containing the JSON doc
\r
424 * @param keys full key path to the target value in the format of "key1.key2.key3..."
\r
425 * @return boolean field value associated with keys - default is false
\r
427 public static boolean getJsonBooleanValue(String jsonStr, String keys) {
\r
429 Object rawValue = getJsonRawValue(jsonStr, keys);
\r
430 if (rawValue == null) {
\r
433 if (rawValue instanceof Boolean) {
\r
434 msoLogger.debug("getJsonBooleanValue(): the raw value is a Boolean Object=" + rawValue);
\r
435 return (Boolean) rawValue;
\r
437 msoLogger.debug("getJsonBooleanValue(): the raw value is NOT an Boolean Object=" + rawValue.toString());
\r
441 } catch (Exception e) {
\r
442 msoLogger.debug("getJsonBooleanValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString(),e);
\r
448 * Invokes the getJsonParamValue() method to obtain the JSONArray associated with
\r
449 * the specified keys. The JSONArray is then walked to retrieve the first array
\r
450 * value associated with the specified field name (index=0).
\r
452 * @param jsonStr String containing the JSON doc
\r
453 * @param keys full key path to the target value in the format of "key1.key2.key3..."
\r
454 * @param name field name for the param to be retrieved
\r
455 * @return String param value associated with field name
\r
457 public static String getJsonParamValue(String jsonStr, String keys, String name) {
\r
458 return getJsonParamValue(jsonStr, keys, name, 0);
\r
462 * Invokes the getJsonRawValue() method to obtain the JSONArray associated with
\r
463 * the specified keys. The JSONArray is then walked to retrieve the nth array
\r
464 * value associated with the specified field name and index.
\r
466 * @param jsonStr String containing the JSON doc
\r
467 * @param keys full key path to the target value in the format of "key1.key2.key3..."
\r
468 * @param name field name for the param to be retrieved
\r
469 * @param index the nth param associated with name starting at 0
\r
470 * @return String param value associated with field name
\r
472 public static String getJsonParamValue(String jsonStr, String keys, String name, int index) {
\r
473 // String isDebugLogEnabled = "true";
\r
475 Object rawValue = getJsonRawValue(jsonStr, keys);
\r
476 if (rawValue == null) {
\r
479 if (rawValue instanceof JSONArray) {
\r
480 msoLogger.debug("getJsonParamValue(): keys=" + keys + " points to JSONArray: " + rawValue.toString());
\r
481 int arrayLen = ((JSONArray) rawValue).length();
\r
482 if (index < 0 || arrayLen < index+1) {
\r
483 msoLogger.debug("getJsonParamValue(): index: " + index + " is out of bounds for array size of " + arrayLen);
\r
487 for (int i = 0; i < arrayLen; i++) {
\r
488 msoLogger.debug("getJsonParamValue(): index: " + i + ", value: " + ((JSONArray) rawValue).get(i).toString());
\r
489 if (((JSONArray) rawValue).get(i) instanceof JSONObject) {
\r
490 // msoLogger.debug("getJsonParamValue(): index: " + i + " is a JSONObject");
\r
491 JSONObject jsonObj = (JSONObject)((JSONArray) rawValue).get(i);
\r
492 String parmValue = jsonObj.get(name).toString();
\r
493 if (parmValue != null) {
\r
494 msoLogger.debug("getJsonParamValue(): found value: " + parmValue + " for name: " + name + " and index: " + i);
\r
495 if (foundCnt == index) {
\r
505 msoLogger.debug("getJsonParamValue(): the JSONArray element is NOT a JSONObject=" + rawValue.toString());
\r
509 msoLogger.debug("getJsonParamValue(): content value NOT found for name: " + name);
\r
512 msoLogger.debug("getJsonParamValue(): the raw value is NOT a JSONArray Object=" + rawValue.toString());
\r
516 } catch (Exception e) {
\r
517 // JSONObject::get() throws a "not found" exception if one of the specified keys is not found
\r
518 if (e.getMessage().contains("not found")) {
\r
519 msoLogger.debug("getJsonParamValue(): failed to retrieve param value for keys:" + keys + ", name=" + name + ": " + e.getMessage());
\r
521 msoLogger.debug("getJsonParamValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString(), e);
\r
528 * Wrapper to generate the JSONObject to pass to the getJsonValueForKey(JSONObject, String)
\r
529 * method so that recursion over the subobjects can be supported there
\r
531 * @param jsonStr String containing the JSON doc
\r
532 * @param key key to the target value
\r
533 * @return String field value associated with key
\r
535 public static String getJsonValueForKey(String jsonStr, String key) {
\r
536 // String isDebugLogEnabled = "true";
\r
538 JSONObject jsonObj = new JSONObject(jsonStr);
\r
539 return getJsonValueForKey(jsonObj, key);
\r
540 } catch (Exception e) {
\r
541 msoLogger.debug("getJsonValueForKey(): unable to parse json to retrieve value for field=" + key + ". Exception was: " + e.toString(), e);
\r
547 * Walks the JSONObject (and sub-objects recursively), searching for the first value associated with the
\r
548 * single key/field name specified. Returns the associated value if found or null if the key is not found
\r
550 * @param jsonObj JSONObject representation of the the JSON doc
\r
551 * @param key key to the target value
\r
552 * @return String field value associated with key
\r
554 public static String getJsonValueForKey(JSONObject jsonObj, String key) {
\r
555 // String isDebugLogEnabled = "true";
\r
556 String keyValue = null;
\r
558 if (jsonObj.has(key)) {
\r
559 Object value = jsonObj.get(key);
\r
560 msoLogger.debug("getJsonValueForKey(): found value=" + (String) value + ", for key=" + key);
\r
561 if (value == null) {
\r
564 return ((String) value);
\r
567 // msoLogger.debug("getJsonValueForKey(): iterating over the keys");
\r
568 Iterator <String> itr = jsonObj.keys();
\r
569 while (itr.hasNext()) {
\r
570 String nextKey = itr.next();
\r
571 Object obj = jsonObj.get(nextKey);
\r
572 if (obj instanceof JSONObject) {
\r
573 // msoLogger.debug("getJsonValueForKey(): key=" + nextKey + ", points to JSONObject, recursive call on: " +
\r
574 // ((JSONObject) obj).toString(MSOJsonIndentFactor));
\r
575 keyValue = getJsonValueForKey((JSONObject) obj, key);
\r
576 if (keyValue != null) {
\r
577 // msoLogger.debug("getJsonValueForKey(): found value=" + keyValue + ", for key=" + key);
\r
581 msoLogger.debug("getJsonValueForKey(): key=" + nextKey + ", does not point to a JSONObject, next key");
\r
585 } catch (Exception e) {
\r
586 // JSONObject::get() throws a "not found" exception if one of the specified keys is not found
\r
587 if (e.getMessage().contains("not found")) {
\r
588 msoLogger.debug("getJsonValueForKey(): failed to retrieve param value for key=" + key + ": " + e.getMessage());
\r
590 msoLogger.debug("getJsonValueForKey(): unable to parse json to retrieve value for field=" + key + ". Exception was: " + e.toString(), e);
\r
598 * Walks the JSONObject (and sub-objects recursively), searching for the first value associated with the
\r
599 * single key/field name specified. Returns the associated value if found or null if the key is not found
\r
601 * @param jsonObj JSONObject representation of the the JSON doc
\r
602 * @param key key to the target value
\r
603 * @return String field value associated with key
\r
605 public static Integer getJsonIntValueForKey(JSONObject jsonObj, String key) {
\r
606 // String isDebugLogEnabled = "true";
\r
607 Integer keyValue = null;
\r
609 if (jsonObj.has(key)) {
\r
610 Integer value = (Integer) jsonObj.get(key);
\r
611 msoLogger.debug("getJsonIntValueForKey(): found value=" + value + ", for key=" + key);
\r
614 // msoLogger.debug("getJsonIntValueForKey(): iterating over the keys");
\r
615 Iterator <String> itr = jsonObj.keys();
\r
616 while (itr.hasNext()) {
\r
617 String nextKey = itr.next();
\r
618 Object obj = jsonObj.get(nextKey);
\r
619 if (obj instanceof JSONObject) {
\r
620 // msoLogger.debug("getJsonIntValueForKey(): key=" + nextKey + ", points to JSONObject, recursive call");
\r
621 keyValue = getJsonIntValueForKey((JSONObject) obj, key);
\r
622 if (keyValue != null) {
\r
623 // msoLogger.debug("getJsonIntValueForKey(): found value=" + keyValue + ", for key=" + key);
\r
627 msoLogger.debug("getJsonIntValueForKey(): key=" + nextKey + ", does not point to a JSONObject, next key");
\r
631 } catch (Exception e) {
\r
632 // JSONObject::get() throws a "not found" exception if one of the specified keys is not found
\r
633 if (e.getMessage().contains("not found")) {
\r
634 msoLogger.debug("getJsonIntValueForKey(): failed to retrieve param value for key=" + key + ": " + e.getMessage());
\r
636 msoLogger.debug("getJsonIntValueForKey(): unable to parse json to retrieve value for field=" + key + ". Exception was: " + e.toString(),e);
\r
644 * Walks the JSONObject (and sub-objects recursively), searching for the first value associated with the
\r
645 * single key/field name specified. Returns the associated value if found or null if the key is not found
\r
647 * @param jsonObj JSONObject representation of the the JSON doc
\r
648 * @param key key to the target value
\r
649 * @return String field value associated with key
\r
651 public static Boolean getJsonBooleanValueForKey(JSONObject jsonObj, String key) {
\r
652 Boolean keyValue = null;
\r
654 if (jsonObj.has(key)) {
\r
655 Boolean value = (Boolean) jsonObj.get(key);
\r
656 msoLogger.debug("getJsonBooleanValueForKey(): found value=" + value + ", for key=" + key);
\r
659 // msoLogger.debug("getJsonBooleanValueForKey(): iterating over the keys");
\r
660 Iterator <String> itr = jsonObj.keys();
\r
661 while (itr.hasNext()) {
\r
662 String nextKey = itr.next();
\r
663 Object obj = jsonObj.get(nextKey);
\r
664 if (obj instanceof JSONObject) {
\r
665 // msoLogger.debug("getJsonBooleanValueForKey(): key=" + nextKey + ", points to JSONObject, recursive call");
\r
666 keyValue = getJsonBooleanValueForKey((JSONObject) obj, key);
\r
667 if (keyValue != null) {
\r
668 // msoLogger.debug("getJsonBooleanValueForKey(): found value=" + keyValue + ", for key=" + key);
\r
672 msoLogger.debug("getJsonBooleanValueForKey(): key=" + nextKey + ", does not point to a JSONObject, next key");
\r
676 } catch (Exception e) {
\r
677 // JSONObject::get() throws a "not found" exception if one of the specified keys is not found
\r
678 if (e.getMessage().contains("not found")) {
\r
679 msoLogger.debug("getJsonBooleanValueForKey(): failed to retrieve param value for key=" + key + ": " + e.getMessage());
\r
681 msoLogger.debug("getJsonBooleanValueForKey(): unable to parse json to retrieve value for field=" + key + ". Exception was: " + e.toString(),e);
\r
689 * Boolean method to determine if a key path is valid for the JSON doc. Invokes
\r
692 * @param jsonStr String containing the JSON doc
\r
693 * @param keys full key path to the target value in the format of "key1.key2.key3..."
\r
694 * @return Boolean true if keys points to value in the JSON doc
\r
696 public static Boolean jsonValueExists(String jsonStr, String keys) {
\r
697 if (getJsonRawValue(jsonStr, keys) == null) {
\r
705 * Inserts the new key/value pair at the appropriate location in the JSON
\r
706 * document after first determining if keyed field already exists. If
\r
707 * it does exist, return the JSON unmodified, otherwise return the new JSON
\r
708 * Note: this method currently only supports String value inserts.
\r
710 * @param jsonStr String containing the JSON doc
\r
711 * @param keys full key path to the value to be added in the format of "key1.key2.key3..."
\r
712 * @return String containing the updated JSON doc
\r
714 public static String addJsonValue(String jsonStr, String keys, String value) {
\r
715 // String isDebugLogEnabled = "true";
\r
716 // only attempt to insert the key/value pair if it does not exist
\r
717 if (!jsonValueExists(jsonStr, keys)) {
\r
718 return putJsonValue(jsonStr, keys, value);
\r
720 msoLogger.debug("addJsonValue(): JSON add failed, key=" + keys + "/value=" + value + " already exists");
\r
726 * Updates the value for the specified key in the JSON document
\r
727 * after first determining if keyed field exists. If it does
\r
728 * not exist, return the JSON unmodified, otherwise return the updated JSON.
\r
729 * Note: this method currently only supports String value updates.
\r
731 * @param jsonStr String containing the JSON doc
\r
732 * @param keys full key path to the value to be updated in the format of "key1.key2.key3..."
\r
733 * @return String containing the updated JSON doc
\r
735 public static String updJsonValue(String jsonStr, String keys, String newValue) {
\r
736 // String isDebugLogEnabled = "true";
\r
737 // only attempt to modify the key/value pair if it exists
\r
738 if (jsonValueExists(jsonStr, keys)) {
\r
739 return putJsonValue(jsonStr, keys, newValue);
\r
741 msoLogger.debug("updJsonValue(): JSON update failed, no value exists for key=" + keys);
\r
747 * Deletes the value for the specified key in the JSON document
\r
748 * after first determining if keyed field exists. If it does
\r
749 * not exist, return the JSON unmodified, otherwise return the updated JSON
\r
751 * @param jsonStr String containing the JSON doc
\r
752 * @param keys full key path to the value to be deleted in the format of "key1.key2.key3..."
\r
753 * @return String containing the updated JSON doc
\r
755 public static String delJsonValue(String jsonStr, String keys) {
\r
756 // String isDebugLogEnabled = "true";
\r
757 // only attempt to remove the key/value pair if it exists
\r
758 if (jsonValueExists(jsonStr, keys)) {
\r
759 // passing a null value results in a delete
\r
760 return putJsonValue(jsonStr, keys, null);
\r
762 msoLogger.debug("delJsonValue(): JSON delete failed, no value exists for key=" + keys);
\r
768 * Walks the JSON doc using the full key path to retrieve the associated
\r
769 * value. All but the last key points to the 'parent' object name(s) in order
\r
770 * in the JSON hierarchy with the last key pointing to the target value.
\r
771 * The value returned is a Java object.
\r
773 * @param jsonStr String containing the JSON doc
\r
774 * @param keys full key path to the target value in the format of "key1.key2.key3..."
\r
775 * @return Object field value associated with keys
\r
777 private static Object getJsonRawValue(String jsonStr, String keys) {
\r
778 return getJsonRawValue(jsonStr, keys, false);
\r
782 * Walks the JSON doc using the full key path to retrieve the associated
\r
783 * value. All but the last key points to the 'parent' object name(s) in order
\r
784 * in the JSON hierarchy with the last key pointing to the target value.
\r
785 * The value returned is a Java object.
\r
787 * @param jsonStr String containing the JSON doc
\r
788 * @param keys full key path to the target value in the format of "key1.key2.key3..."
\r
789 * @param wrap Boolean which determines if returned JSONObjects sould be "wrapped"
\r
790 * Note: wrap does not apply to returned scalar values
\r
791 * @return Object field value associated with keys
\r
793 private static Object getJsonRawValue(String jsonStr, String keys, Boolean wrap) {
\r
794 // String isDebugLogEnabled = "true";
\r
795 String keyStr = "";
\r
797 JSONObject jsonObj = new JSONObject(jsonStr);
\r
798 StringTokenizer keyTokens = new StringTokenizer(keys, ".");
\r
799 while (keyTokens.hasMoreElements()) {
\r
800 keyStr = keyTokens.nextToken();
\r
801 Object keyValue = jsonObj.get(keyStr);
\r
802 if (keyValue instanceof JSONObject) {
\r
803 // msoLogger.debug("getJsonRawValue(): key=" + keyStr + " points to json object");
\r
804 jsonObj = (JSONObject) keyValue;
\r
806 if (keyTokens.hasMoreElements()) {
\r
807 msoLogger.debug("getJsonRawValue(): value found prior to last key for key=" + keyStr);
\r
812 // return the json 'node' that the key points to
\r
813 // note: since this is a json object and not a scalar value,
\r
814 // use the wrap flag to determine if the object should
\r
815 // be wrapped with a root node value
\r
816 // (the last key in the keys String)
\r
818 JSONObject wrappedJsonObj = new JSONObject();
\r
819 wrappedJsonObj.put(keyStr, jsonObj);
\r
820 return wrappedJsonObj.toString();
\r
822 return jsonObj.toString();
\r
825 } catch (Exception e) {
\r
826 // JSONObject::get() throws a "not found" exception if one of the specified keys is not found
\r
827 if (e.getMessage().contains("not found")) {
\r
828 msoLogger.debug("getJsonRawValue(): failed to retrieve param value for key=" + keyStr + ": " + e.getMessage());
\r
830 msoLogger.debug("getJsonRawValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString(),e);
\r
837 * Private method invoked by the public add, update, and delete methods.
\r
839 * @param jsonStr String containing the JSON doc
\r
840 * @param keys full key path to the value to be deleted in the format of "key1.key2.key3..."
\r
841 * @return String containing the updated JSON doc
\r
843 private static String putJsonValue(String jsonStr, String keys, String value) {
\r
844 // String isDebugLogEnabled = "true";
\r
845 String keyStr = "";
\r
847 JSONObject jsonObj = new JSONObject(jsonStr);
\r
848 JSONObject jsonObjOut = jsonObj;
\r
849 StringTokenizer keyTokens = new StringTokenizer(keys, ".");
\r
850 while (keyTokens.hasMoreElements()) {
\r
851 keyStr = keyTokens.nextToken();
\r
852 if (keyTokens.hasMoreElements()) {
\r
853 Object keyValue = jsonObj.get(keyStr);
\r
854 if (keyValue instanceof JSONObject) {
\r
855 // msoLogger.debug("putJsonValue(): key=" + keyStr + " points to json object");
\r
856 jsonObj = (JSONObject) keyValue;
\r
858 msoLogger.debug("putJsonValue(): key=" + keyStr + " not the last key but points to non-json object: " + keyValue);
\r
861 } else { // at the last/new key value
\r
862 jsonObj.put(keyStr, value);
\r
863 return jsonObjOut.toString(3);
\r
866 // should not hit this point if the key points to a valid key value
\r
869 } catch (Exception e) {
\r
870 // JSONObject::get() throws a "not found" exception if one of the specified keys is not found
\r
871 if (e.getMessage().contains("not found")) {
\r
872 msoLogger.debug("putJsonValue(): failed to put param value for key=" + keyStr + ": " + e.getMessage());
\r
874 msoLogger.debug("putJsonValue(): unable to parse json to put value for key=" + keys + ". Exception was: " + e.toString(),e);
\r
881 * This json util method converts a json array of Key Value
\r
882 * pair objects into a Java Map.
\r
885 * @param entryArray - the getJsonValue of a json Array of key/value pairs
\r
887 * @return Map - a Map containing the entries
\r
889 public Map<String, String> jsonStringToMap(DelegateExecution execution, String entry) {
\r
890 msoLogger.debug("Started Json String To Map Method");
\r
892 Map<String, String> map = new HashMap<>();
\r
895 JSONObject obj = new JSONObject(entry);
\r
897 /* Wildfly is pushing a version of org.json which does not
\r
898 * auto cast to string. Leaving it as an object prevents
\r
899 * a method not found exception at runtime.
\r
901 final Iterator<String> keys = obj.keys();
\r
902 while (keys.hasNext()) {
\r
903 final String key = keys.next();
\r
904 map.put(key, obj.getString(key));
\r
906 msoLogger.debug("Outgoing Map is: " + map);
\r
907 msoLogger.debug("Completed Json String To Map Method");
\r
912 * This json util method converts a json array of Key Value
\r
913 * pair objects into a Java Map.
\r
916 * @param entryArray - the getJsonValue of a json Array of key/value pairs
\r
917 * @param keyNode - the name of the node that represents the key
\r
918 * @param valueNode - the name of the node that represents the value
\r
920 * @return Map - a Map containing the entries
\r
923 public Map<String, String> entryArrayToMap(DelegateExecution execution, String entryArray, String keyNode, String valueNode) {
\r
924 msoLogger.debug("Started Entry Array To Map Util Method");
\r
926 Map<String, String> map = new HashMap<>();
\r
928 String entryListJson = "{ \"wrapper\":" + entryArray + "}";
\r
929 JSONObject obj = new JSONObject(entryListJson);
\r
930 JSONArray arr = obj.getJSONArray("wrapper");
\r
931 for (int i = 0; i < arr.length(); i++){
\r
932 JSONObject jo = arr.getJSONObject(i);
\r
933 String key = jo.getString(keyNode);
\r
934 String value =jo.getString(valueNode);
\r
935 map.put(key, value);
\r
937 msoLogger.debug("Outgoing Map is: " + map);
\r
938 msoLogger.debug("Completed Entry Array To Map Util Method");
\r
943 * This json util method converts a json Array of Strings
\r
944 * to a Java List. It takes each String in the json Array
\r
945 * and puts it in a Java List<String>.
\r
948 * @param jsonArrayOfStrings - the getJsonValue of a json array of strings
\r
950 * @return List - a java list containing the strings
\r
954 public List<String> StringArrayToList(Execution execution, String jsonArrayOfStrings) {
\r
955 msoLogger.debug("Started String Array To List Util Method");
\r
957 List<String> list = new ArrayList<>();
\r
959 String stringListJson = "{ \"strings\":" + jsonArrayOfStrings + "}";
\r
960 JSONObject obj = new JSONObject(stringListJson);
\r
961 JSONArray arr = obj.getJSONArray("strings");
\r
962 for (int i = 0; i < arr.length(); i++){
\r
963 String s = arr.get(i).toString();
\r
966 msoLogger.debug("Outgoing List is: " + list);
\r
967 msoLogger.debug("Completed String Array To List Util Method");
\r
973 * Invokes the getJsonRawValue() method to determine if the
\r
974 * json element/variable exist. Returns true if the
\r
975 * json element exist
\r
977 * @param jsonStr String containing the JSON doc
\r
978 * @param keys full key path to the target value in the format of "key1.key2.key3..."
\r
979 * @return boolean field value associated with keys
\r
983 public static boolean jsonElementExist(String jsonStr, String keys) {
\r
986 Object rawValue = getJsonRawValue(jsonStr, keys);
\r
988 return !(rawValue == null);
\r
990 } catch (Exception e) {
\r
991 msoLogger.debug("jsonElementExist(): unable to determine if json element exist. Exception is: " + e.toString(),e);
\r
998 * Validates the JSON document against a schema file.
\r
1000 * @param jsonStr String containing the JSON doc
\r
1001 * @param jsonSchemaPath full path to a valid JSON schema file
\r
1002 * @return String the validation results/report
\r
1006 public static String jsonSchemaValidation(String jsonStr, String jsonSchemaPath) throws ValidationException {
\r
1008 msoLogger.debug("JSON document to be validated: " + jsonStr);
\r
1009 JsonNode document = JsonLoader.fromString(jsonStr);
\r
1010 // JsonNode document = JsonLoader.fromFile(jsonDoc);
\r
1011 JsonNode schema = JsonLoader.fromPath(jsonSchemaPath);
\r
1013 JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
\r
1014 JsonValidator validator = factory.getValidator();
\r
1016 ProcessingReport report = validator.validate(schema, document);
\r
1017 msoLogger.debug("JSON schema validation report: " + report.toString());
\r
1018 return report.toString();
\r
1019 } catch (IOException e) {
\r
1020 msoLogger.debug("IOException performing JSON schema validation on document: " + e.toString());
\r
1021 throw new ValidationException(e.getMessage());
\r
1022 } catch (ProcessingException e) {
\r
1023 msoLogger.debug("ProcessingException performing JSON schema validation on document: " + e.toString());
\r
1024 throw new ValidationException(e.getMessage());
\r