/*
* Copyright 2013 the original author or authors.
*
* Licensed 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 io.jdev.miniprofiler.json;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Utility class used for JSON serialization.
*/
public class JsonUtil {
public static List<Map<String, Object>> mapList(List<? extends Jsonable> srcList) {
if (srcList == null) {
return null;
}
List<Map<String, Object>> dest = new ArrayList<Map<String, Object>>(srcList.size());
for (Jsonable srcObject : srcList) {
dest.add(srcObject != null ? srcObject.toMap() : null);
}
return dest;
}
public static String toJson(Jsonable src) {
StringBuilder buf = new StringBuilder();
mapToJsonBuffer(buf, src.toMap());
return buf.toString();
}
private static void objectToJsonBuffer(StringBuilder buf, Object obj) {
if (obj == null) {
buf.append("null");
} else if (obj instanceof Jsonable) {
mapToJsonBuffer(buf, ((Jsonable) obj).toMap()); //
} else if (obj instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) obj;
mapToJsonBuffer(buf, map); //
} else if (obj instanceof Collection) {
collectionToJsonBuffer(buf, (Collection) obj);
} else if (obj instanceof Number || obj instanceof Boolean) {
buf.append(obj.toString());
} else {
// treat it like a string, regardless
stringToJsonBuffer(buf, obj.toString());
}
}
private static void stringToJsonBuffer(StringBuilder buf, String str) {
if (str == null) {
buf.append("null");
} else {
quote(str, buf);
}
}
/**
* Produce a string in double quotes with backslash sequences in all the
* right places. A backslash will be inserted within </, allowing JSON
* text to be delivered in HTML. In JSON text, a string cannot contain a
* control character or an unescaped quote or backslash.
*
* This code copied from The Jettison project JSONObject class, also under
* the Apcache 2.0 license.
*
* @param string A String
* @param sb buffer to append to
*/
public static void quote(String string, StringBuilder sb) {
char c = 0;
int i;
int len = string.length();
String t;
sb.append('"');
for (i = 0; i < len; i += 1) {
c = string.charAt(i);
switch (c) {
case '\\':
case '"':
sb.append('\\');
sb.append(c);
break;
case '/':
sb.append('\\');
sb.append(c);
break;
case '\b':
sb.append("\\b");
break;
case '\t':
sb.append("\\t");
break;
case '\n':
sb.append("\\n");
break;
case '\f':
sb.append("\\f");
break;
case '\r':
sb.append("\\r");
break;
default:
if (c < ' ') {
t = "000" + Integer.toHexString(c);
sb.append("\\u" + t.substring(t.length() - 4));
} else {
sb.append(c);
}
}
}
sb.append('"');
}
private static void collectionToJsonBuffer(StringBuilder buf, Collection<?> src) {
buf.append("[");
boolean first = true;
for (Object val : src) {
if (first) {
first = false;
} else {
buf.append(',');
}
objectToJsonBuffer(buf, val);
}
buf.append("]");
}
private static void mapToJsonBuffer(StringBuilder buf, Map<String, ?> src) {
buf.append("{");
boolean first = true;
for (Map.Entry<String, ?> entry : src.entrySet()) {
if (first) {
first = false;
} else {
buf.append(',');
}
stringToJsonBuffer(buf, entry.getKey());
buf.append(':');
objectToJsonBuffer(buf, entry.getValue());
}
buf.append("}");
}
}