blob: b65ea27fbe94efe0dfc5b775e211f4512ac1c877 [file] [log] [blame]
/*
* 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.karaf.features.internal.util;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
/**
*/
public final class JsonWriter {
private JsonWriter() {
}
public static void write(OutputStream stream, Object value) throws IOException {
write(stream, value, false);
}
public static void write(OutputStream stream, Object value, boolean format) throws IOException {
Writer writer = new OutputStreamWriter(stream);
write(writer, value, format);
writer.flush();
}
public static void write(Writer writer, Object value) throws IOException {
write(writer, value, false);
}
public static void write(Writer writer, Object value, boolean format) throws IOException {
int indent = format ? 0 : -1;
write(writer, value, indent);
}
private static void write(Writer writer, Object value, int indent) throws IOException {
if (value instanceof Map) {
writeObject(writer, (Map) value, indent);
} else if (value instanceof Collection) {
writeArray(writer, (Collection) value, indent);
} else if (value instanceof Number) {
writeNumber(writer, (Number) value);
} else if (value instanceof String) {
writeString(writer, (String) value);
} else if (value instanceof Boolean) {
writeBoolean(writer, (Boolean) value);
} else if (value == null) {
writeNull(writer);
} else {
throw new IllegalArgumentException("Unsupported value: " + value);
}
}
private static void writeObject(Writer writer, Map<?, ?> value, int indent) throws IOException {
writer.append('{');
boolean first = true;
for (Map.Entry entry : value.entrySet()) {
if (!first) {
writer.append(',');
} else {
first = false;
}
if (indent >= 0) {
indent(writer, indent + 1);
}
writeString(writer, (String) entry.getKey());
if (indent >= 0) {
writer.append(' ');
}
writer.append(':');
if (indent >= 0) {
writer.append(' ');
}
write(writer, entry.getValue(), indent + 1);
}
if (indent >= 0) {
indent(writer, indent);
}
writer.append('}');
}
private static void writeString(Writer writer, String value) throws IOException {
writer.append('"');
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
switch (c) {
case '\"':
writer.append("\\\"");
break;
case '\\':
writer.append("\\\\");
break;
case '\b':
writer.append("\\b");
break;
case '\f':
writer.append("\\f");
break;
case '\n':
writer.append("\\n");
break;
case '\r':
writer.append("\\r");
break;
case '\t':
writer.append("\\t");
break;
default:
if (c < ' ' || (c >= '\u0080' && c < '\u00a0') || (c >= '\u2000' && c < '\u2100')) {
String s = Integer.toHexString(c);
writer.append('\\');
writer.append('u');
for (int j = s.length(); j < 4; j++) {
writer.append('0');
}
writer.append(s);
} else {
writer.append(c);
}
break;
}
}
writer.append('"');
}
private static void writeNumber(Writer writer, Number value) throws IOException {
writer.append(value.toString());
}
private static void writeBoolean(Writer writer, Boolean value) throws IOException {
writer.append(Boolean.toString(value));
}
private static void writeArray(Writer writer, Collection<?> value, int indent) throws IOException {
writer.append('[');
boolean first = true;
for (Object obj : value) {
if (!first) {
writer.append(',');
} else {
first = false;
}
if (indent >= 0) {
indent(writer, indent + 1);
}
write(writer, obj, indent + 1);
}
if (indent >= 0) {
indent(writer, indent);
}
writer.append(']');
}
private static void writeNull(Writer writer) throws IOException {
writer.append("null");
}
static char[] INDENT;
static {
INDENT = new char[1];
Arrays.fill(INDENT, '\t');
}
private static void indent(Writer writer, int indent) throws IOException {
writer.write("\n");
while (indent > INDENT.length) {
char[] a = new char[INDENT.length * 2];
Arrays.fill(a, '\t');
INDENT = a;
}
writer.write(INDENT, 0, indent);
}
}