2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
7 * ================================================================================
8 * Modifications Copyright (c) 2019 Samsung
9 * ================================================================================
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 * ============LICENSE_END=========================================================
24 package org.onap.so.bpmn.core.json;
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.List;
32 import java.util.StringTokenizer;
34 import org.camunda.bpm.engine.delegate.DelegateExecution;
35 import org.camunda.bpm.engine.runtime.Execution;
36 import org.json.JSONArray;
37 import org.json.JSONException;
38 import org.json.JSONObject;
40 import org.onap.so.bpmn.core.xml.XmlTool;
41 import org.onap.so.exceptions.ValidationException;
43 import com.fasterxml.jackson.databind.JsonNode;
44 import com.github.fge.jackson.JsonLoader;
45 import com.github.fge.jsonschema.core.exceptions.ProcessingException;
46 import com.github.fge.jsonschema.core.report.ProcessingReport;
47 import com.github.fge.jsonschema.main.JsonSchemaFactory;
48 import com.github.fge.jsonschema.main.JsonValidator;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
53 * Utility class for JSON processing
57 * Note: It was observed, that depending on the JSON implementation, an org.json.JSONException or a
58 * java.util.NoSuchElementException will be thrown in the event of the key value being "not found"
59 * in a JSON document. A general check has been added to the applicable catch blocks for this
60 * this type of behavior to reduce the amount of logging. As a key value not being found is
61 * expect behavior, it makes no sense to log the stack trace associated with this type of failure.
63 public class JsonUtils {
65 private static Logger logger = LoggerFactory.getLogger(JsonUtils.class);
66 private static int MSOJsonIndentFactor = 3;
69 * Uses the JSONObject static method to convert a XML doc to JSON.
71 * @param xml String containing the XML doc
72 * @param pretty flag to determine if the output should be formatted
73 * @return String containing the JSON translation
75 public static String xml2json(String xml, Boolean pretty) {
77 // name spaces cause problems, so just remove them
78 JSONObject jsonObj = XML.toJSONObject(XmlTool.removeNamespaces(xml));
80 return jsonObj.toString();
82 // add an indent to make it 'pretty'
83 return jsonObj.toString(MSOJsonIndentFactor);
85 } catch (Exception e){
86 logger.debug("xml2json(): unable to parse xml and convert to json. Exception was: {}", e.toString(), e);
92 * Invokes xml2json(String, Boolean) defaulting to 'pretty' output.
94 * @param xml String containing the XML doc
95 * @return String containing the JSON translation
97 public static String xml2json(String xml) {
98 return xml2json(xml, true);
102 * Uses the JSONObject static method to convert a JSON doc to XML.
103 * Note: this method may not generate valid XML if the JSONObject
104 * contains JSONArrays which are used to represent XML attributes
107 * @param jsonStr String containing the JSON doc
108 * @param pretty flag to determine if the output should be formatted
109 * @return String containing the XML translation
111 public static String json2xml(String jsonStr, Boolean pretty) {
114 JSONObject jsonObj = new JSONObject(jsonStr);
116 // use the local class method which properly handles certain JSONArray content
117 return XmlTool.normalize(toXMLString(jsonObj, null));
119 // use the local class method which properly handles certain JSONArray content
120 return toXMLString(jsonObj, null);
122 } catch (Exception e){
123 logger.debug("json2xml(): unable to parse json and convert to xml. Exception was: {}", e.toString(), e);
129 * Uses a modified version of the org.json.XML toString() algorithm
130 * to convert a JSONObject to an XML Doc. The intent of this is to
131 * correctly generate XML from JSON including TAGs for JSONArrays
133 * @param obj org.json.JSON object to be converted to XML
134 * @param tagName optional XML tagname supplied primarily during recursive calls
135 * @return String containing the XML translation
137 public static String toXMLString(Object obj, String tagName) throws JSONException {
138 StringBuilder strBuf = new StringBuilder();
143 Iterator<String> keys;
147 if (obj instanceof JSONObject) {
148 // append "<tagName>" to the XML output
149 if (tagName != null) {
151 strBuf.append(tagName);
154 // iterate thru the keys.
155 jsonObj = (JSONObject) obj;
156 keys = jsonObj.keys();
157 while (keys.hasNext()) {
159 curObj = jsonObj.opt(key);
160 if (curObj == null) {
163 if (curObj instanceof String) {
164 str = (String) curObj;
168 // append the content to the XML output
169 if ("content".equals(key)) {
170 if (curObj instanceof JSONArray) {
171 jsonArr = (JSONArray) curObj;
172 len = jsonArr.length();
173 for (i = 0; i < len; i += 1) {
177 strBuf.append(XML.escape(jsonArr.get(i).toString()));
180 strBuf.append(XML.escape(curObj.toString()));
182 // append an array of similar keys to the XML output
183 } else if (curObj instanceof JSONArray) {
184 jsonArr = (JSONArray) curObj;
185 len = jsonArr.length();
186 for (i = 0; i < len; i += 1) {
187 curObj = jsonArr.get(i);
188 if (curObj instanceof JSONArray) {
189 // The XML tags for the nested array should be generated below when this method
190 // is called recursively and the JSONArray object is passed
191 // strBuf.append("<");
192 // strBuf.append(key);
193 // strBuf.append(">");
194 strBuf.append(toXMLString(curObj, null));
195 // strBuf.append("</");
196 // strBuf.append(key);
197 // strBuf.append(">");
199 // append the opening tag for the array (before 1st element)
205 // append the opening tag for the array
206 strBuf.append(toXMLString(curObj, null));
207 // append the closing tag for the array (after last element)
208 if (i == (len - 1)) {
215 } else if (curObj.equals("")) {
216 // append a closing tag "<key>" to the XML output
221 strBuf.append(toXMLString(curObj, key));
224 if (tagName != null) {
225 // append the closing tag "</tagName>" to the XML output
227 strBuf.append(tagName);
230 return strBuf.toString();
231 // XML does not have good support for arrays. If an array appears in a place
232 // where XML is lacking, synthesize an < array > element.
233 } else if (obj instanceof JSONArray) {
234 jsonArr = (JSONArray) obj;
235 len = jsonArr.length();
236 for (i = 0; i < len; ++i) {
237 curObj = jsonArr.opt(i);
238 strBuf.append(toXMLString(curObj, (tagName == null) ? "array"
241 return strBuf.toString();
243 str = (obj == null) ? "null" : XML.escape(obj.toString());
244 return (tagName == null) ? "\"" + str + "\""
245 : (str.length() == 0) ? "<" + tagName + "/>" : "<"
246 + tagName + ">" + str + "</" + tagName + ">";
251 * Invokes json2xml(String, Boolean) defaulting to 'pretty' output.
253 * @param jsonStr String containing the XML doc
254 * @return String containing the JSON translation
256 public static String json2xml(String jsonStr) {
257 return json2xml(jsonStr, true);
261 * Formats the JSON String using the value of MSOJsonIndentFactor.
263 * @param jsonStr String containing the JSON doc
264 * @return String containing the formatted JSON doc
266 public static String prettyJson(String jsonStr) {
268 JSONObject jsonObj = new JSONObject(jsonStr);
269 return jsonObj.toString(MSOJsonIndentFactor);
270 } catch (Exception e){
271 logger.debug("prettyJson(): unable to parse/format json input. Exception was: {}", e.toString(), e);
277 * Returns an Iterator over the JSON keys in the specified JSON doc.
279 * @param jsonStr String containing the JSON doc
280 * @return Iterator over the JSON keys
281 * @throws JSONException if the doc cannot be parsed
283 public static Iterator <String> getJsonIterator(String jsonStr) throws JSONException {
284 return new JSONObject(jsonStr).keys();
288 * Returns the name of the "root" property in the specified JSON doc. The
289 * "root" property is the single top-level property in the JSON doc. An
290 * exception is thrown if the doc is empty or if it contains more than one
291 * top-level property.
293 * @param jsonStr String containing the JSON doc
294 * @return the name of the "root" property
295 * @throws JSONException if the doc cannot be parsed, or if it is empty, or if
296 * it contains more than one top-level property
298 public static String getJsonRootProperty(String jsonStr) throws JSONException {
299 Iterator<String> iter = getJsonIterator(jsonStr);
301 if (!iter.hasNext()) {
302 throw new JSONException("Empty JSON object");
305 String rootPropertyName = iter.next();
307 if (iter.hasNext()) {
308 throw new JSONException("JSON object has more than one root property");
311 return rootPropertyName;
315 * Invokes the getJsonRawValue() method and returns the String equivalent of
316 * the object returned.
318 * TBD: May need separate methods for boolean, float, and integer fields if the
319 * String representation is not sufficient to meet client needs.
321 * @param jsonStr String containing the JSON doc
322 * @param keys full key path to the target value in the format of "key1.key2.key3..."
323 * @return String field value associated with keys
325 public static String getJsonValue(String jsonStr, String keys) {
327 Object rawValue = getJsonRawValue(jsonStr, keys);
328 if (rawValue == null) {
331 if (rawValue instanceof String) {
332 logger.debug("getJsonValue(): the raw value is a String Object={}", rawValue);
333 return (String) rawValue;
335 logger.debug("getJsonValue(): the raw value is NOT a String Object={}", rawValue.toString());
336 return rawValue.toString();
339 } catch (Exception e) {
340 logger.debug("getJsonValue(): unable to parse json to retrieve value for field={}. Exception was: {}", keys,
347 * Invokes the getJsonRawValue() method with the wrap flag set to true
348 * and returns the String equivalent of the json node object returned.
350 * @param jsonStr String containing the JSON doc
351 * @param keys full key path to the target value in the format of "key1.key2.key3..."
352 * @return String field value associated with keys
354 public static String getJsonNodeValue(String jsonStr, String keys) {
356 Object rawValue = getJsonRawValue(jsonStr, keys, true);
357 if (rawValue == null) {
360 if (rawValue instanceof String) {
361 logger.debug("getJsonNodeValue(): the raw value is a String Object={}", rawValue);
362 return (String) rawValue;
364 logger.debug("getJsonNodeValue(): the raw value is NOT a String Object={}", rawValue.toString());
365 return rawValue.toString();
368 } catch (Exception e) {
369 logger.debug("getJsonNodeValue(): unable to parse json to retrieve node for field={}. Exception was: {}", keys,
376 * Invokes the getJsonRawValue() method and returns the String equivalent of
377 * the object returned.
379 * TBD: May need separate methods for boolean, float, and integer fields if the
380 * String representation is not sufficient to meet client needs.
382 * @param jsonStr String containing the JSON doc
383 * @param keys full key path to the target value in the format of "key1.key2.key3..."
384 * @return String field value associated with keys
386 public static int getJsonIntValue(String jsonStr, String keys) {
388 Object rawValue = getJsonRawValue(jsonStr, keys);
389 if (rawValue == null) {
392 if (rawValue instanceof Integer) {
393 logger.debug("getJsonIntValue(): the raw value is an Integer Object={}", ((String) rawValue).toString());
394 return (Integer) rawValue;
396 logger.debug("getJsonIntValue(): the raw value is NOT an Integer Object={}", rawValue.toString());
400 } catch (Exception e) {
401 logger.debug("getJsonIntValue(): unable to parse json to retrieve value for field={}. Exception was: {}", keys,
408 * Invokes the getJsonRawValue() method and returns the boolean equivalent of
409 * the object returned.
411 * @param jsonStr String containing the JSON doc
412 * @param keys full key path to the target value in the format of "key1.key2.key3..."
413 * @return boolean field value associated with keys - default is false
415 public static boolean getJsonBooleanValue(String jsonStr, String keys) {
417 Object rawValue = getJsonRawValue(jsonStr, keys);
418 if (rawValue == null) {
421 if (rawValue instanceof Boolean) {
422 logger.debug("getJsonBooleanValue(): the raw value is a Boolean Object={}", rawValue);
423 return (Boolean) rawValue;
425 logger.debug("getJsonBooleanValue(): the raw value is NOT an Boolean Object={}", rawValue.toString());
429 } catch (Exception e) {
430 logger.debug("getJsonBooleanValue(): unable to parse json to retrieve value for field={}. Exception was: {}", keys,
437 * Invokes the getJsonParamValue() method to obtain the JSONArray associated with
438 * the specified keys. The JSONArray is then walked to retrieve the first array
439 * value associated with the specified field name (index=0).
441 * @param jsonStr String containing the JSON doc
442 * @param keys full key path to the target value in the format of "key1.key2.key3..."
443 * @param name field name for the param to be retrieved
444 * @return String param value associated with field name
446 public static String getJsonParamValue(String jsonStr, String keys, String name) {
447 return getJsonParamValue(jsonStr, keys, name, 0);
451 * Invokes the getJsonRawValue() method to obtain the JSONArray associated with
452 * the specified keys. The JSONArray is then walked to retrieve the nth array
453 * value associated with the specified field name and index.
455 * @param jsonStr String containing the JSON doc
456 * @param keys full key path to the target value in the format of "key1.key2.key3..."
457 * @param name field name for the param to be retrieved
458 * @param index the nth param associated with name starting at 0
459 * @return String param value associated with field name
461 public static String getJsonParamValue(String jsonStr, String keys, String name, int index) {
463 Object rawValue = getJsonRawValue(jsonStr, keys);
464 if (rawValue == null) {
467 if (rawValue instanceof JSONArray) {
468 logger.debug("getJsonParamValue(): keys={} points to JSONArray: {}", keys, rawValue.toString());
469 int arrayLen = ((JSONArray) rawValue).length();
470 if (index < 0 || arrayLen < index+1) {
471 logger.debug("getJsonParamValue(): index: {} is out of bounds for array size of {}", index, arrayLen);
475 for (int i = 0; i < arrayLen; i++) {
476 logger.debug("getJsonParamValue(): index: {}, value: {}", i, ((JSONArray) rawValue).get(i).toString());
477 if (((JSONArray) rawValue).get(i) instanceof JSONObject) {
478 JSONObject jsonObj = (JSONObject)((JSONArray) rawValue).get(i);
479 String parmValue = jsonObj.get(name).toString();
480 if (parmValue != null) {
481 logger.debug("getJsonParamValue(): found value: {} for name: {} and index: {}", parmValue, name, i);
482 if (foundCnt == index) {
492 logger.debug("getJsonParamValue(): the JSONArray element is NOT a JSONObject={}", rawValue.toString());
496 logger.debug("getJsonParamValue(): content value NOT found for name: {}", name);
499 logger.debug("getJsonParamValue(): the raw value is NOT a JSONArray Object={}", rawValue.toString());
503 } catch (Exception e) {
504 if (e.getMessage().contains("not found")) {
505 logger.debug("getJsonParamValue(): failed to retrieve param value for keys:{}, name={} : {}", keys, name,
508 logger.debug("getJsonParamValue(): unable to parse json to retrieve value for field={}. Exception was: {}", keys,
516 * Wrapper to generate the JSONObject to pass to the getJsonValueForKey(JSONObject, String)
517 * method so that recursion over the subobjects can be supported there
519 * @param jsonStr String containing the JSON doc
520 * @param key key to the target value
521 * @return String field value associated with key
523 public static String getJsonValueForKey(String jsonStr, String key) {
526 JSONObject jsonObj = new JSONObject(jsonStr);
527 return getJsonValueForKey(jsonObj, key);
528 } catch (Exception e) {
529 logger.debug("getJsonValueForKey(): unable to parse json to retrieve value for field={}. Exception was: {}", key,
536 * Walks the JSONObject (and sub-objects recursively), searching for the first value associated with the
537 * single key/field name specified. Returns the associated value if found or null if the key is not found
539 * @param jsonObj JSONObject representation of the the JSON doc
540 * @param key key to the target value
541 * @return String field value associated with key
543 public static String getJsonValueForKey(JSONObject jsonObj, String key) {
545 String keyValue = null;
547 if (jsonObj.has(key)) {
548 Object value = jsonObj.get(key);
549 logger.debug("getJsonValueForKey(): found value={}, for key={}", (String) value, key);
553 return ((String) value);
556 Iterator <String> itr = jsonObj.keys();
557 while (itr.hasNext()) {
558 String nextKey = itr.next();
559 Object obj = jsonObj.get(nextKey);
560 if (obj instanceof JSONObject) {
561 keyValue = getJsonValueForKey((JSONObject) obj, key);
562 if (keyValue != null) {
566 logger.debug("getJsonValueForKey(): key={}, does not point to a JSONObject, next key", nextKey);
570 } catch (Exception e) {
571 // JSONObject::get() throws a "not found" exception if one of the specified keys is not found
572 if (e.getMessage().contains("not found")) {
573 logger.debug("getJsonValueForKey(): failed to retrieve param value for key={}: {}", key, e.getMessage());
575 logger.debug("getJsonValueForKey(): unable to parse json to retrieve value for field={}. Exception was {}", key,
584 * Walks the JSONObject (and sub-objects recursively), searching for the first value associated with the
585 * single key/field name specified. Returns the associated value if found or null if the key is not found
587 * @param jsonObj JSONObject representation of the the JSON doc
588 * @param key key to the target value
589 * @return String field value associated with key
591 public static Integer getJsonIntValueForKey(JSONObject jsonObj, String key) {
592 Integer keyValue = null;
594 if (jsonObj.has(key)) {
595 Integer value = (Integer) jsonObj.get(key);
596 logger.debug("getJsonIntValueForKey(): found value={}, for key={}", value, key);
599 Iterator <String> itr = jsonObj.keys();
600 while (itr.hasNext()) {
601 String nextKey = itr.next();
602 Object obj = jsonObj.get(nextKey);
603 if (obj instanceof JSONObject) {
604 keyValue = getJsonIntValueForKey((JSONObject) obj, key);
605 if (keyValue != null) {
609 logger.debug("getJsonIntValueForKey(): key={}, does not point to a JSONObject, next key", nextKey);
613 } catch (Exception e) {
614 // JSONObject::get() throws a "not found" exception if one of the specified keys is not found
615 if (e.getMessage().contains("not found")) {
616 logger.debug("getJsonIntValueForKey(): failed to retrieve param value for key={}: {}", key, e.getMessage());
618 logger.debug("getJsonIntValueForKey(): unable to parse json to retrieve value for field={}. Exception was: {}", key,
627 * Walks the JSONObject (and sub-objects recursively), searching for the first value associated with the
628 * single key/field name specified. Returns the associated value if found or null if the key is not found
630 * @param jsonObj JSONObject representation of the the JSON doc
631 * @param key key to the target value
632 * @return String field value associated with key
634 public static Boolean getJsonBooleanValueForKey(JSONObject jsonObj, String key) {
635 Boolean keyValue = null;
637 if (jsonObj.has(key)) {
638 Boolean value = (Boolean) jsonObj.get(key);
639 logger.debug("getJsonBooleanValueForKey(): found value={}, for key={}", value, key);
642 Iterator <String> itr = jsonObj.keys();
643 while (itr.hasNext()) {
644 String nextKey = itr.next();
645 Object obj = jsonObj.get(nextKey);
646 if (obj instanceof JSONObject) {
647 keyValue = getJsonBooleanValueForKey((JSONObject) obj, key);
648 if (keyValue != null) {
652 logger.debug("getJsonBooleanValueForKey(): key={}, does not point to a JSONObject, next key", nextKey);
656 } catch (Exception e) {
657 // JSONObject::get() throws a "not found" exception if one of the specified keys is not found
658 if (e.getMessage().contains("not found")) {
659 logger.debug("getJsonBooleanValueForKey(): failed to retrieve param value for key={}: {}", key, e.getMessage());
661 logger.debug("getJsonBooleanValueForKey(): unable to parse json to retrieve value for field={}. Exception was: {}",
662 key, e.toString(), e);
670 * Boolean method to determine if a key path is valid for the JSON doc. Invokes
673 * @param jsonStr String containing the JSON doc
674 * @param keys full key path to the target value in the format of "key1.key2.key3..."
675 * @return Boolean true if keys points to value in the JSON doc
677 public static Boolean jsonValueExists(String jsonStr, String keys) {
678 if (getJsonRawValue(jsonStr, keys) == null) {
686 * Inserts the new key/value pair at the appropriate location in the JSON
687 * document after first determining if keyed field already exists. If
688 * it does exist, return the JSON unmodified, otherwise return the new JSON
689 * Note: this method currently only supports String value inserts.
691 * @param jsonStr String containing the JSON doc
692 * @param keys full key path to the value to be added in the format of "key1.key2.key3..."
693 * @return String containing the updated JSON doc
695 public static String addJsonValue(String jsonStr, String keys, String value) {
697 // only attempt to insert the key/value pair if it does not exist
698 if (!jsonValueExists(jsonStr, keys)) {
699 return putJsonValue(jsonStr, keys, value);
701 logger.debug("addJsonValue(): JSON add failed, key={}/value={} already exists", keys, value);
707 * Updates the value for the specified key in the JSON document
708 * after first determining if keyed field exists. If it does
709 * not exist, return the JSON unmodified, otherwise return the updated JSON.
710 * Note: this method currently only supports String value updates.
712 * @param jsonStr String containing the JSON doc
713 * @param keys full key path to the value to be updated in the format of "key1.key2.key3..."
714 * @return String containing the updated JSON doc
716 public static String updJsonValue(String jsonStr, String keys, String newValue) {
717 // only attempt to modify the key/value pair if it exists
718 if (jsonValueExists(jsonStr, keys)) {
719 return putJsonValue(jsonStr, keys, newValue);
721 logger.debug("updJsonValue(): JSON update failed, no value exists for key={}", keys);
727 * Deletes the value for the specified key in the JSON document
728 * after first determining if keyed field exists. If it does
729 * not exist, return the JSON unmodified, otherwise return the updated JSON
731 * @param jsonStr String containing the JSON doc
732 * @param keys full key path to the value to be deleted in the format of "key1.key2.key3..."
733 * @return String containing the updated JSON doc
735 public static String delJsonValue(String jsonStr, String keys) {
737 // only attempt to remove the key/value pair if it exists
738 if (jsonValueExists(jsonStr, keys)) {
739 // passing a null value results in a delete
740 return putJsonValue(jsonStr, keys, null);
742 logger.debug("delJsonValue(): JSON delete failed, no value exists for key={}", keys);
748 * Walks the JSON doc using the full key path to retrieve the associated
749 * value. All but the last key points to the 'parent' object name(s) in order
750 * in the JSON hierarchy with the last key pointing to the target value.
751 * The value returned is a Java object.
753 * @param jsonStr String containing the JSON doc
754 * @param keys full key path to the target value in the format of "key1.key2.key3..."
755 * @return Object field value associated with keys
757 private static Object getJsonRawValue(String jsonStr, String keys) {
758 return getJsonRawValue(jsonStr, keys, false);
762 * Walks the JSON doc using the full key path to retrieve the associated
763 * value. All but the last key points to the 'parent' object name(s) in order
764 * in the JSON hierarchy with the last key pointing to the target value.
765 * The value returned is a Java object.
767 * @param jsonStr String containing the JSON doc
768 * @param keys full key path to the target value in the format of "key1.key2.key3..."
769 * @param wrap Boolean which determines if returned JSONObjects sould be "wrapped"
770 * Note: wrap does not apply to returned scalar values
771 * @return Object field value associated with keys
773 private static Object getJsonRawValue(String jsonStr, String keys, Boolean wrap) {
777 JSONObject jsonObj = new JSONObject(jsonStr);
778 StringTokenizer keyTokens = new StringTokenizer(keys, ".");
779 while (keyTokens.hasMoreElements()) {
780 keyStr = keyTokens.nextToken();
781 Object keyValue = jsonObj.get(keyStr);
782 if (keyValue instanceof JSONObject) {
783 jsonObj = (JSONObject) keyValue;
785 if (keyTokens.hasMoreElements()) {
786 logger.debug("getJsonRawValue(): value found prior to last key for key={}", keyStr);
791 // return the json 'node' that the key points to
792 // note: since this is a json object and not a scalar value,
793 // use the wrap flag to determine if the object should
794 // be wrapped with a root node value
795 // (the last key in the keys String)
797 JSONObject wrappedJsonObj = new JSONObject();
798 wrappedJsonObj.put(keyStr, jsonObj);
799 return wrappedJsonObj.toString();
801 return jsonObj.toString();
804 } catch (Exception e) {
805 // JSONObject::get() throws a "not found" exception if one of the specified keys is not found
806 if (e.getMessage().contains("not found")) {
807 logger.debug("getJsonRawValue(): failed to retrieve param value for key={}: {}", keyStr, e.getMessage());
809 logger.debug("getJsonRawValue(): unable to parse json to retrieve value for field={}. Exception was: {}", keys,
817 * Private method invoked by the public add, update, and delete methods.
819 * @param jsonStr String containing the JSON doc
820 * @param keys full key path to the value to be deleted in the format of "key1.key2.key3..."
821 * @return String containing the updated JSON doc
823 private static String putJsonValue(String jsonStr, String keys, String value) {
827 JSONObject jsonObj = new JSONObject(jsonStr);
828 JSONObject jsonObjOut = jsonObj;
829 StringTokenizer keyTokens = new StringTokenizer(keys, ".");
830 while (keyTokens.hasMoreElements()) {
831 keyStr = keyTokens.nextToken();
832 if (keyTokens.hasMoreElements()) {
833 Object keyValue = jsonObj.get(keyStr);
834 if (keyValue instanceof JSONObject) {
835 jsonObj = (JSONObject) keyValue;
837 logger.debug("putJsonValue(): key={} not the last key but points to non-json object: {}", keyStr, keyValue);
840 } else { // at the last/new key value
841 jsonObj.put(keyStr, value);
842 return jsonObjOut.toString(3);
845 // should not hit this point if the key points to a valid key value
848 } catch (Exception e) {
849 // JSONObject::get() throws a "not found" exception if one of the specified keys is not found
850 if (e.getMessage().contains("not found")) {
851 logger.debug("putJsonValue(): failed to put param value for key={}: {}", keyStr, e.getMessage());
853 logger.debug("putJsonValue(): unable to parse json to put value for key={}. Exception was: {}", keys, e.toString(),
861 * This json util method converts a json array of Key Value
862 * pair objects into a Java Map.
865 * @param entryArray - the getJsonValue of a json Array of key/value pairs
867 * @return Map - a Map containing the entries
869 public Map<String, String> jsonStringToMap(DelegateExecution execution, String entry) {
870 logger.debug("Started Json String To Map Method");
872 Map<String, String> map = new HashMap<>();
875 JSONObject obj = new JSONObject(entry);
877 /* Wildfly is pushing a version of org.json which does not
878 * auto cast to string. Leaving it as an object prevents
879 * a method not found exception at runtime.
881 final Iterator<String> keys = obj.keys();
882 while (keys.hasNext()) {
883 final String key = keys.next();
884 map.put(key, obj.getString(key));
886 logger.debug("Outgoing Map is: {}", map);
887 logger.debug("Completed Json String To Map Method");
892 * This json util method converts a json array of Key Value
893 * pair objects into a Java Map.
896 * @param entryArray - the getJsonValue of a json Array of key/value pairs
897 * @param keyNode - the name of the node that represents the key
898 * @param valueNode - the name of the node that represents the value
899 * @return Map - a Map containing the entries
902 public Map<String, String> entryArrayToMap(DelegateExecution execution, String entryArray, String keyNode, String valueNode) {
903 logger.debug("Started Entry Array To Map Util Method");
905 Map<String, String> map = new HashMap<>();
907 String entryListJson = "{ \"wrapper\":" + entryArray + "}";
908 JSONObject obj = new JSONObject(entryListJson);
909 JSONArray arr = obj.getJSONArray("wrapper");
910 for (int i = 0; i < arr.length(); i++){
911 JSONObject jo = arr.getJSONObject(i);
912 String key = jo.getString(keyNode);
913 String value = jo.get(valueNode).toString();
916 logger.debug("Completed Entry Array To Map Util Method");
921 * This json util method converts a json array of Key Value pair objects into a Java Map.
923 * @param entryArray - the json Array of key/value pairs objects
924 * @param keyNode - the name of the node that represents the key
925 * @param valueNode - the name of the node that represents the value
926 * @return Map - a Map containing the entries
930 public Map<String, String> entryArrayToMap(String entryArray, String keyNode, String valueNode){
931 logger.debug("Started Entry Array To Map Util Method");
933 Map<String, String> map = new HashMap<>();
934 String entryListJson = "{ \"wrapper\":" + entryArray + "}";
935 JSONObject obj = new JSONObject(entryListJson); // TODO just put in json array
936 JSONArray arr = obj.getJSONArray("wrapper");
937 for(int i = 0; i < arr.length(); i++){
938 JSONObject jo = arr.getJSONObject(i);
939 String key = jo.getString(keyNode);
940 String value = jo.get(valueNode).toString();
943 logger.debug("Completed Entry Array To Map Util Method");
948 * This json util method converts a json Array of Strings to a Java List. It takes each
949 * String in the json Array and puts it in a Java List<String>.
952 * @param jsonArray - string value of a json array
953 * @return List - a java list containing the strings
957 public List<String> StringArrayToList(Execution execution, String jsonArray){
958 logger.debug("Started String Array To List Util Method");
960 List<String> list = new ArrayList<>();
963 String stringListJson = "{ \"strings\":" + jsonArray + "}";
964 JSONObject obj = new JSONObject(stringListJson);
965 JSONArray arr = obj.getJSONArray("strings");
966 for(int i = 0; i < arr.length(); i++){
967 String s = arr.get(i).toString();
970 logger.debug("Outgoing List is: {}", list);
971 logger.debug("Completed String Array To List Util Method");
976 * This json util method converts a json Array of Strings to a Java List. It takes each
977 * String in the json Array and puts it in a Java List<String>.
979 * @param jsonArray - string value of a json array
980 * @return List - a java list containing the strings
984 public List<String> StringArrayToList(String jsonArray){
985 logger.debug("Started Json Util String Array To List");
986 List<String> list = new ArrayList<>();
988 JSONArray arr = new JSONArray(jsonArray);
989 for(int i = 0; i < arr.length(); i++){
990 String s = arr.get(i).toString();
993 logger.debug("Completed Json Util String Array To List");
998 * This json util method converts a json Array of Strings to a Java List. It takes each
999 * String in the json Array and puts it in a Java List<String>.
1001 * @param jsonArray - json array
1002 * @return List - a java list containing the strings
1006 public List<String> StringArrayToList(JSONArray jsonArray){
1007 logger.debug("Started Json Util String Array To List");
1008 List<String> list = new ArrayList<>();
1010 for(int i = 0; i < jsonArray.length(); i++){
1011 String s = jsonArray.get(i).toString();
1014 logger.debug("Completed Json Util String Array To List");
1020 * Invokes the getJsonRawValue() method to determine if the json element/variable exist.
1021 * Returns true if the json element exist
1023 * @param jsonStr - String containing the JSON doc
1024 * @param keys - full key path to the target value in the format of "key1.key2.key3..."
1025 * @return boolean field value associated with keys
1028 public static boolean jsonElementExist(String jsonStr, String keys){
1031 Object rawValue = getJsonRawValue(jsonStr, keys);
1033 return !(rawValue == null);
1035 } catch(Exception e){
1036 logger.debug("jsonElementExist(): unable to determine if json element exist. Exception is: {}", e.toString(), e);
1043 * Validates the JSON document against a schema file.
1045 * @param jsonStr String containing the JSON doc
1046 * @param jsonSchemaPath full path to a valid JSON schema file
1049 public static String jsonSchemaValidation(String jsonStr, String jsonSchemaPath) throws ValidationException {
1051 logger.debug("JSON document to be validated: {}", jsonStr);
1052 JsonNode document = JsonLoader.fromString(jsonStr);
1053 JsonNode schema = JsonLoader.fromPath(jsonSchemaPath);
1055 JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
1056 JsonValidator validator = factory.getValidator();
1058 ProcessingReport report = validator.validate(schema, document);
1059 logger.debug("JSON schema validation report: {}", report.toString());
1060 return report.toString();
1061 } catch (IOException e) {
1062 logger.debug("IOException performing JSON schema validation on document: {}", e.toString());
1063 throw new ValidationException(e.getMessage());
1064 } catch (ProcessingException e) {
1065 logger.debug("ProcessingException performing JSON schema validation on document: {}", e.toString());
1066 throw new ValidationException(e.getMessage());