2 * ================================================================================
3 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * ============LICENSE_END=========================================================
20 package org.onap.dcae.analytics.model.util.function;
22 import com.fasterxml.jackson.databind.JsonNode;
23 import com.fasterxml.jackson.databind.ObjectMapper;
25 import java.io.IOException;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.LinkedHashMap;
30 import java.util.function.Function;
32 import org.onap.dcae.analytics.model.configbindingservice.ConfigBindingServiceConstants;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
37 * Converts JSON String to flatten map of key value pair
39 * @author Rajiv Singla
41 public class JsonStringToMapFunction implements Function<String, Map<String, Object>> {
43 private static final Logger logger = LoggerFactory.getLogger(JsonStringToMapFunction.class);
45 private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
46 private final String keyPrefix;
47 private final String keySeparator;
49 public JsonStringToMapFunction(final String keyPrefix, final String keySeparator) {
50 this.keyPrefix = keyPrefix;
51 this.keySeparator = keySeparator;
54 public JsonStringToMapFunction(final String keyPrefix) {
55 this(keyPrefix, ConfigBindingServiceConstants.KEY_SEPARATOR);
58 public JsonStringToMapFunction() {
59 this("", ConfigBindingServiceConstants.KEY_SEPARATOR);
63 @SuppressWarnings("unchecked")
64 public Map<String, Object> apply(final String jsonString) {
66 logger.debug("Converting JSON to flattened key value Map: {}", jsonString);
67 if (jsonString == null || jsonString.trim().isEmpty()) {
68 return new HashMap<>();
71 final Map<String, Object> result = flattenJson(jsonString);
72 logger.debug("Flattened Key Value Pairs");
73 result.forEach((key, value) -> logger.debug("{}:{}", key, value));
78 * Flattens Json String
80 * @param jsonString json String
82 * @return map containing flattened json string key and value
84 private Map<String, Object> flattenJson(final String jsonString) {
87 final JsonNode rootNode = OBJECT_MAPPER.readTree(jsonString);
88 final LinkedHashMap<String, Object> result = new LinkedHashMap<>();
89 flattenJsonNode(keyPrefix, rootNode, result);
91 } catch (IOException e) {
92 final String errorMessage = String.format("Unable to flatten JSON String to Map. Invalid JSON String: " +
94 logger.error(errorMessage, e, jsonString);
95 throw new IllegalArgumentException(jsonString, e);
101 * Flattens json array
103 * @param propertyPrefix property prefix
104 * @param jsonNodesIterator json array node that needs to be flattened
105 * @param resultMap result map containing flattened key value pairs
107 private void flattenJsonArray(String propertyPrefix, Iterator<JsonNode> jsonNodesIterator,
108 Map<String, Object> resultMap) {
110 while (jsonNodesIterator.hasNext()) {
111 flattenJsonNode(propertyPrefix + "[" + counter + "]", jsonNodesIterator.next(), resultMap);
118 * Flattens json array
120 * @param propertyPrefix property prefix
121 * @param objectNode json object node that needs to be flattened
122 * @param resultMap result map containing flattened key value pairs
124 private void flattenJsonMap(String propertyPrefix, JsonNode objectNode,
125 Map<String, Object> resultMap) {
126 final Iterator<Map.Entry<String, JsonNode>> fieldsIterator = objectNode.fields();
127 while (fieldsIterator.hasNext()) {
128 final Map.Entry<String, JsonNode> fieldEntry = fieldsIterator.next();
129 final JsonNode jsonValue = fieldEntry.getValue();
130 final String jsonKey = fieldEntry.getKey();
132 (propertyPrefix.isEmpty() ? "" : propertyPrefix + keySeparator) + jsonKey,
133 jsonValue, resultMap);
138 * Checks various elements types of JSON Types and flattens them based on their type
140 * @param propertyPrefix property prefix
141 * @param currentJsonNode currentJsonNode that may need to be flattened
142 * @param resultMap result map containing flattened key value pairs
144 private void flattenJsonNode(final String propertyPrefix, final JsonNode currentJsonNode,
145 final Map<String, Object> resultMap) {
148 if (currentJsonNode.isObject()) {
149 flattenJsonMap(propertyPrefix, currentJsonNode, resultMap);
150 } else if (currentJsonNode.isArray()) {
151 flattenJsonArray(propertyPrefix, currentJsonNode.iterator(), resultMap);
153 resultMap.put(propertyPrefix, getObjectValue(currentJsonNode));
157 private static Object getObjectValue(final JsonNode jsonNode) {
158 if (jsonNode.isTextual()) {
159 return jsonNode.textValue();
160 } else if (jsonNode.isNumber()) {
161 return jsonNode.asLong();
162 } else if (jsonNode.isBoolean()) {
163 return jsonNode.asBoolean();
165 return jsonNode.asText();