2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.mso.bpmn.core.json;
23 import java.util.Iterator;
24 import java.util.StringTokenizer;
26 import org.json.JSONArray;
27 import org.json.JSONException;
28 import org.json.JSONObject;
31 //import org.openecomp.mso.bpmn.core.BPMNLogger;
32 import org.openecomp.mso.bpmn.core.xml.XmlTool;
33 import org.openecomp.mso.logger.MsoLogger;
36 * Utility class for JSON processing
41 public class JsonUtils {
43 private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL);
44 private static int MSOJsonIndentFactor = 3;
47 * Uses the JSONObject static method to convert a XML doc to JSON.
49 * @param xml String containing the XML doc
50 * @param pretty flag to determine if the output should be formatted
51 * @return String containing the JSON translation
53 public static String xml2json(String xml, Boolean pretty) {
54 // String isDebugLogEnabled = "true";
56 // name spaces cause problems, so just remove them
57 JSONObject jsonObj = XML.toJSONObject(XmlTool.removeNamespaces(xml));
59 return jsonObj.toString();
61 // add an indent to make it 'pretty'
62 return jsonObj.toString(MSOJsonIndentFactor);
64 } catch (Exception e){
65 msoLogger.debug("xml2json(): unable to parse xml and convert to json. Exception was: " + e.toString());
71 * Invokes xml2json(String, Boolean) defaulting to 'pretty' output.
73 * @param xml String containing the XML doc
74 * @return String containing the JSON translation
76 public static String xml2json(String xml) {
77 return xml2json(xml, true);
81 * Uses the JSONObject static method to convert a JSON doc to XML.
82 * Note: this method will not generate valid XML if the JSONObject
83 * contains JSONArrays which are used to represent XML attributes
86 * @param jsonStr String containing the JSON doc
87 * @param pretty flag to determine if the output should be formatted
88 * @return String containing the XML translation
90 public static String json2xml(String jsonStr, Boolean pretty) {
91 // String isDebugLogEnabled = "true";
93 JSONObject jsonObj = new JSONObject(jsonStr);
95 return XmlTool.normalize(XML.toString(jsonObj));
97 return XML.toString(jsonObj);
99 } catch (Exception e){
100 msoLogger.debug("json2xml(): unable to parse json and convert to xml. Exception was: " + e.toString());
106 * Invokes json2xml(String, Boolean) defaulting to 'pretty' output.
108 * @param jsonStr String containing the XML doc
109 * @return String containing the JSON translation
111 public static String json2xml(String jsonStr) {
112 return json2xml(jsonStr, true);
116 * Uses the JSONObject static method to convert a JSON doc to XML.
118 * @param jsonStr String containing the JSON doc
119 * @return Iterator over the JSON keys
121 public static Iterator <String> getJsonIterator(String jsonStr) {
122 // String isDebugLogEnabled = "true";
124 JSONObject json = new JSONObject(jsonStr);
127 } catch (Exception e){
128 msoLogger.debug("getJsonIterator(): unable to parse json to retrieve the keys iterator. Exception was: " + e.toString());
134 * Invokes the getJsonRawValue() method and returns the String equivalent of
135 * the object returned.
137 * TBD: May need separate methods for boolean, float, and integer fields if the
138 * String representation is not sufficient to meet client needs.
140 * @param jsonStr String containing the JSON doc
141 * @param keys full key path to the target value in the format of "key1.key2.key3..."
142 * @return String field value associated with keys
144 public static String getJsonValue(String jsonStr, String keys) {
145 // String isDebugLogEnabled = "true";
147 Object rawValue = getJsonRawValue(jsonStr, keys);
148 if (rawValue == null) {
151 if (rawValue instanceof String) {
152 msoLogger.debug("getJsonValue(): the raw value is a String Object=" + ((String) rawValue).toString());
153 return (String) rawValue;
155 msoLogger.debug("getJsonValue(): the raw value is NOT a String Object=" + rawValue.toString());
156 return rawValue.toString();
159 } catch (Exception e) {
160 msoLogger.debug("getJsonValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString());
166 * Invokes the getJsonRawValue() method to obtain the JSONArray associated with
167 * the specified keys. The JSONArray is then walked to retrieve the content value of
168 * the specified field name.
170 * @param jsonStr String containing the JSON doc
171 * @param keys full key path to the target value in the format of "key1.key2.key3..."
172 * @param name field name for the param to be retrieved
173 * @return String param value associated with field name
175 public static String getJsonParamValue(String jsonStr, String keys, String name) {
176 // String isDebugLogEnabled = "true";
178 Object rawValue = getJsonRawValue(jsonStr, keys);
179 if (rawValue == null) {
182 if (rawValue instanceof JSONArray) {
183 msoLogger.debug("getJsonParamValue(): keys=" + keys + " points to JSONArray: " + ((JSONArray) rawValue).toString());
184 for (int i = 0; i < ((JSONArray) rawValue).length(); i++) {
185 msoLogger.debug("getJsonParamValue(): index: " + i + ", value: " + ((JSONArray) rawValue).get(i).toString());
186 if (((JSONArray) rawValue).get(i) instanceof JSONObject) {
187 msoLogger.debug("getJsonParamValue(): index: " + i + " is a JSONObject");
188 JSONObject jsonObj = (JSONObject)((JSONArray) rawValue).get(i);
189 if (jsonObj.get("name").equals(name)) {
190 msoLogger.debug("getJsonParamValue(): found value: " + (String) jsonObj.get("content") + " for name: " + name);
191 return (String) jsonObj.get("content");
194 msoLogger.debug("getJsonParamValue(): the JSONArray element is NOT a JSONObject=" + rawValue.toString());
198 msoLogger.debug("getJsonParamValue(): content value NOT found for name: " + name);
201 msoLogger.debug("getJsonParamValue(): the raw value is NOT a JSONArray Object=" + rawValue.toString());
205 } catch (JSONException je) {
206 // JSONObject::get() throws this exception if one of the specified keys is not found
207 msoLogger.debug("getJsonParamValue(): caught JSONException attempting to retrieve param value for keys:" + keys + ", name=" + name);
208 } catch (Exception e) {
209 msoLogger.debug("getJsonParamValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString());
215 * Wrapper to generate the JSONObject to pass to the getJsonValueForKey(JSONObject, String)
216 * method so that recursion over the subobjects can be supported there
218 * @param jsonStr String containing the JSON doc
219 * @param key key to the target value
220 * @return String field value associated with key
222 public static String getJsonValueForKey(String jsonStr, String key) {
223 // String isDebugLogEnabled = "true";
225 JSONObject jsonObj = new JSONObject(jsonStr);
226 if (jsonObj != null) {
227 return getJsonValueForKey(jsonObj, key);
229 } catch (Exception e) {
230 msoLogger.debug("getJsonValueForKey(): unable to parse json to retrieve value for field=" + key + ". Exception was: " + e.toString());
236 * Walks the JSONObject (and sub-objects recursively), searching for the first value associated with the
237 * single key/field name specified. Returns the associated value if found or null if the key is not found
239 * @param jsonObj JSONObject representation of the the JSON doc
240 * @param key key to the target value
241 * @return String field value associated with key
243 public static String getJsonValueForKey(JSONObject jsonObj, String key) {
244 // String isDebugLogEnabled = "true";
245 String keyValue = null;
247 if (jsonObj.has(key)) {
248 msoLogger.debug("getJsonValueForKey(): found value for key=" + key);
249 return ((String) jsonObj.get(key));
251 msoLogger.debug("getJsonValueForKey(): iterating over the keys");
252 Iterator <String> itr = jsonObj.keys();
253 while (itr.hasNext()) {
254 String nextKey = (String) itr.next();
255 Object obj = jsonObj.get(nextKey);
256 if (obj instanceof JSONObject) {
257 msoLogger.debug("getJsonValueForKey(): key=" + nextKey + ", points to JSONObject, recursive call");
258 keyValue = getJsonValueForKey((JSONObject) obj, key);
259 if (keyValue != null) {
260 msoLogger.debug("getJsonValueForKey(): found value=" + keyValue + ", for key=" + key);
264 msoLogger.debug("getJsonValueForKey(): key=" + nextKey + ", does not point to a JSONObject, next key");
268 } catch (JSONException je) {
269 // JSONObject::get() throws this exception if one of the specified keys is not found
270 msoLogger.debug("getJsonValueForKey(): caught JSONException attempting to retrieve value for key=" + key);
272 } catch (Exception e) {
273 msoLogger.debug("getJsonValueForKey(): unable to parse json to retrieve value for field=" + key + ". Exception was: " + e.toString());
279 * Boolean method to determine if a key path is valid for the JSON doc. Invokes
282 * @param jsonStr String containing the JSON doc
283 * @param keys full key path to the target value in the format of "key1.key2.key3..."
284 * @return Boolean true if keys points to value in the JSON doc
286 public static Boolean jsonValueExists(String jsonStr, String keys) {
287 if (getJsonRawValue(jsonStr, keys) == null) {
295 * Inserts the new key/value pair at the appropriate location in the JSON
296 * document after first determining if keyed field already exists. If
297 * it does exist, return the JSON unmodified, otherwise return the new JSON
298 * Note: this method currently only supports String value inserts.
300 * @param jsonStr String containing the JSON doc
301 * @param keys full key path to the value to be added in the format of "key1.key2.key3..."
302 * @return String containing the updated JSON doc
304 public static String addJsonValue(String jsonStr, String keys, String value) {
305 // String isDebugLogEnabled = "true";
306 // only attempt to insert the key/value pair if it does not exist
307 if (!jsonValueExists(jsonStr, keys)) {
308 return putJsonValue(jsonStr, keys, value);
310 msoLogger.debug("addJsonValue(): JSON add failed, key=" + keys + "/value=" + (String) value + " already exists");
316 * Updates the value for the specified key in the JSON document
317 * after first determining if keyed field exists. If it does
318 * not exist, return the JSON unmodified, otherwise return the updated JSON.
319 * Note: this method currently only supports String value updates.
321 * @param jsonStr String containing the JSON doc
322 * @param keys full key path to the value to be updated in the format of "key1.key2.key3..."
323 * @return String containing the updated JSON doc
325 public static String updJsonValue(String jsonStr, String keys, String newValue) {
326 // String isDebugLogEnabled = "true";
327 // only attempt to modify the key/value pair if it exists
328 if (jsonValueExists(jsonStr, keys)) {
329 return putJsonValue(jsonStr, keys, newValue);
331 msoLogger.debug("updJsonValue(): JSON update failed, no value exists for key=" + keys);
337 * Deletes the value for the specified key in the JSON document
338 * after first determining if keyed field exists. If it does
339 * not exist, return the JSON unmodified, otherwise return the updated JSON
341 * @param jsonStr String containing the JSON doc
342 * @param keys full key path to the value to be deleted in the format of "key1.key2.key3..."
343 * @return String containing the updated JSON doc
345 public static String delJsonValue(String jsonStr, String keys) {
346 // String isDebugLogEnabled = "true";
347 // only attempt to remove the key/value pair if it exists
348 if (jsonValueExists(jsonStr, keys)) {
349 // passing a null value results in a delete
350 return putJsonValue(jsonStr, keys, null);
352 msoLogger.debug("delJsonValue(): JSON delete failed, no value exists for key=" + keys);
358 * Walks the JSON doc using the full key path to retrieve the associated
359 * value. All but the last key points to the 'parent' object name(s) in order
360 * in the JSON hierarchy with the last key pointing to the target value.
361 * The value returned is a Java object.
363 * @param jsonStr String containing the JSON doc
364 * @param keys full key path to the target value in the format of "key1.key2.key3..."
365 * @return Object field value associated with keys
367 private static Object getJsonRawValue(String jsonStr, String keys) {
368 // String isDebugLogEnabled = "true";
371 JSONObject jsonObj = new JSONObject(jsonStr);
372 StringTokenizer keyTokens = new StringTokenizer(keys, ".");
373 while (keyTokens.hasMoreElements()) {
374 keyStr = keyTokens.nextToken();
375 Object keyValue = jsonObj.get(keyStr);
376 if (keyValue instanceof JSONObject) {
377 msoLogger.debug("getJsonRawValue(): key=" + keyStr + " points to json object");
378 jsonObj = (JSONObject) keyValue;
380 if (keyTokens.hasMoreElements()) {
381 msoLogger.debug("getJsonRawValue(): value found prior to last key for key=" + keyStr);
386 // we should not hit this point: either the key points to a valid value and
387 // we return it above or the key is invalid and we handle the JSONException
388 // below and return null
391 } catch (JSONException je) {
392 // JSONObject::get() throws this exception if one of the specified keys is not found
393 msoLogger.debug("getJsonRawValue(): caught JSONException attempting to retrieve raw value for key=" + keyStr);
394 } catch (Exception e) {
395 msoLogger.debug("getJsonRawValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString());
401 * Private method invoked by the public add, update, and delete methods.
403 * @param jsonStr String containing the JSON doc
404 * @param keys full key path to the value to be deleted in the format of "key1.key2.key3..."
405 * @return String containing the updated JSON doc
407 private static String putJsonValue(String jsonStr, String keys, String value) {
408 // String isDebugLogEnabled = "true";
411 JSONObject jsonObj = new JSONObject(jsonStr);
412 JSONObject jsonObjOut = jsonObj;
413 StringTokenizer keyTokens = new StringTokenizer(keys, ".");
414 while (keyTokens.hasMoreElements()) {
415 keyStr = keyTokens.nextToken();
416 if (keyTokens.hasMoreElements()) {
417 Object keyValue = jsonObj.get(keyStr);
418 if (keyValue instanceof JSONObject) {
419 msoLogger.debug("putJsonValue(): key=" + keyStr + " points to json object");
420 jsonObj = (JSONObject) keyValue;
422 msoLogger.debug("putJsonValue(): key=" + keyStr + " not the last key but points to non-json object: " + (String) keyValue);
425 } else { // at the last/new key value
426 jsonObj.put(keyStr, value);
427 return jsonObjOut.toString(3);
430 // should not hit this point if the key points to a valid key value
433 } catch (JSONException je) {
434 // JSONObject::get() throws this exception if one of the specified keys is not found
435 msoLogger.debug("putJsonValue(): caught JSONException attempting to retrieve value for key=" + keyStr);
437 } catch (Exception e) {
438 msoLogger.debug("putJsonValue(): unable to parse json to put value for key=" + keys + ". Exception was: " + e.toString());