org.apache.shindig.common.util.JsonConversionUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of shindig-common Show documentation
Show all versions of shindig-common Show documentation
Common java code for Shindig
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.apache.shindig.common.util;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import javax.servlet.http.HttpServletRequest;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Utilities for converting a JSON object to and from a URL encoding
*/
public final class JsonConversionUtil {
private JsonConversionUtil() {}
private static final Pattern ARRAY_MATCH = Pattern.compile("(\\w+)\\((\\d+)\\)");
private static final Set RESERVED_PARAMS = ImmutableSet.of("method", "id", "st", "oauth_token");
@SuppressWarnings("unchecked")
public static JSONObject fromRequest(HttpServletRequest request) throws JSONException {
Map params = request.getParameterMap();
if (!params.containsKey("method")) {
return null;
}
JSONObject root = new JSONObject();
root.put("method", params.get("method")[0]);
if (params.containsKey("id")) {
root.put("id", params.get("id")[0]);
}
JSONObject paramsRoot = new JSONObject();
for (Map.Entry entry : params.entrySet()) {
if (!RESERVED_PARAMS.contains(entry.getKey().toLowerCase())) {
String[] path = StringUtils.splitPreserveAllTokens(entry.getKey(), '.');
JSONObject holder = buildHolder(paramsRoot, path, 0);
holder.put(path[path.length - 1], convertToJsonValue(entry.getValue()[0]));
}
}
if (paramsRoot.length() > 0) {
root.put("params", paramsRoot);
}
return root;
}
public static Map fromJson(JSONObject obj) throws JSONException {
Map result = Maps.newHashMap();
collect(obj, "", result);
return result;
}
private static void collect(Object current, String prefix, Map result)
throws JSONException {
if (current == null) {
result.put(prefix, "null");
return;
}
if (current instanceof JSONObject) {
JSONObject json = (JSONObject) current;
Iterator> keys = json.keys();
while (keys.hasNext()) {
String key = (String) keys.next();
if (json.isNull(key)) {
result.put(prefix + '.' + key, "null");
} else {
collect(json.get(key), prefix + '.' + key, result);
}
}
} else if (current instanceof JSONArray) {
JSONArray jsonArr = (JSONArray) current;
if (isAllLiterals(jsonArr)) {
// The array is all simple value types
String jsonArrayString = jsonArr.toString();
//Strip [ & ]
jsonArrayString = jsonArrayString.substring(1, jsonArrayString.length() - 1);
if (jsonArr.length() == 1) {
jsonArrayString = '(' + jsonArrayString + ')';
}
result.put(prefix, jsonArrayString);
} else {
for (int i = 0; i < jsonArr.length(); i++) {
if (jsonArr.isNull(i)) {
result.put(prefix + '(' + i + ')', "null");
} else {
collect(jsonArr.get(i), prefix + '(' + i + ')', result);
}
}
}
} else {
result.put(prefix, current.toString());
}
}
public static boolean isAllLiterals(JSONArray jsonArr) throws JSONException {
for (int i = 0; i < jsonArr.length(); i++) {
if (!jsonArr.isNull(i) &&
(jsonArr.get(i) instanceof JSONObject ||
jsonArr.get(i) instanceof JSONArray)) {
return false;
}
}
return true;
}
static JSONObject parametersToJsonObject(Map params) throws JSONException {
JSONObject root = new JSONObject();
for (Map.Entry entry : params.entrySet()) {
String[] path = StringUtils.splitPreserveAllTokens(entry.getKey(), '.');
JSONObject holder = buildHolder(root, path, 0);
if (path.length > 1) {
holder.put(path[path.length - 1], convertToJsonValue(entry.getValue()));
} else {
holder.put(path[0], convertToJsonValue(entry.getValue()));
}
}
return root;
}
/**
* Parse the steps in the path into JSON Objects.
*/
static JSONObject buildHolder(JSONObject root, String[] steps, int currentStep)
throws JSONException {
if (currentStep > steps.length - 2) {
return root;
} else {
Matcher matcher = ARRAY_MATCH.matcher(steps[currentStep]);
if (matcher.matches()) {
// Handle as array
String fieldName = matcher.group(1);
int index = Integer.parseInt(matcher.group(2));
JSONArray newArrayStep;
if (root.has(fieldName)) {
newArrayStep = root.getJSONArray(fieldName);
} else {
newArrayStep = new JSONArray();
root.put(fieldName, newArrayStep);
}
JSONObject newStep = new JSONObject();
newArrayStep.put(index, newStep);
return buildHolder(newStep, steps, ++currentStep);
} else {
JSONObject newStep;
if (root.has(steps[currentStep])) {
newStep = root.getJSONObject(steps[currentStep]);
} else {
newStep = new JSONObject();
root.put(steps[currentStep], newStep);
}
return buildHolder(newStep, steps, ++currentStep);
}
}
}
static Object convertToJsonValue(String value) throws JSONException {
if (value == null) {
return null;
} else if (value.startsWith("(") && value.endsWith(")")) {
// explicit form of literal array
return new JSONArray('[' + value.substring(1, value.length() - 1) + ']');
} else {
try {
// inferred parsing of literal array
// Attempt to parse as an array of literals
JSONArray parsedArray = new JSONArray('[' + value + ']');
if (parsedArray.length() == 1) {
// Not an array.
Object obj = parsedArray.get(0);
if (obj instanceof Double && !obj.toString().equals(value)) {
// Numeric overflow or truncation occurred. ie. large int/long
// converted to Double with exponent or Double truncated.
// In Shindig we return this as a verbatim String to avoid
// loss of data on input, as with lengthy ID values consisting
// of only numbers.
return value;
}
return obj;
}
return parsedArray;
} catch (JSONException je) {
return value;
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy