All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.joda.beans.ser.json.JsonOutput Maven / Gradle / Ivy

There is a newer version: 2.11.1
Show newest version
/*
 *  Copyright 2001-present Stephen Colebourne
 *
 *  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 org.joda.beans.ser.json;

import java.io.IOException;
import java.util.BitSet;

/**
 * Outputter for JSON data.
 */
final class JsonOutput {

    /** encoding JSON */
    private static final String[] REPLACE = new String[128];
    static {
        for (int i = 0; i < 32; i++) {
            REPLACE[i] = String.format("\\u%04x", i);
        }
        REPLACE['\b'] = "\\b";
        REPLACE['\t'] = "\\t";
        REPLACE['\n'] = "\\n";
        REPLACE['\f'] = "\\f";
        REPLACE['\r'] = "\\r";
        REPLACE['"'] = "\\\"";
        REPLACE['\\'] = "\\\\";
        REPLACE[127] = "\\u007f";
    }

    /**
     * The appender to write to.
     */
    private final Appendable output;
    /**
     * The indent amount.
     */
    private final String indent;
    /**
     * The new line.
     */
    private final String newLine;
    /**
     * The current indent.
     */
    private String currentIndent = "";
    /**
     * The comma depth.
     */
    private int commaDepth;
    /**
     * The comma state.
     */
    private BitSet commaState = new BitSet(64);

    /**
     * Creates an instance that outputs in compact format.
     * 
     * @param output  the output to write to, not null
     */
    JsonOutput(Appendable output) {
        this(output, "", "");
    }

    /**
     * Creates an instance where the output format can be controlled.
     * 
     * @param output  the output to write to, not null
     * @param indent  the pretty format indent
     * @param newLine  the pretty format new line
     */
    JsonOutput(Appendable output, String indent, String newLine) {
        this.output = output;
        this.indent = indent;
        this.newLine = newLine;
    }

    //-----------------------------------------------------------------------
    /**
     * Writes a JSON null.
     * 
     * @throws IOException if an error occurs
     */
    void writeNull() throws IOException {
        output.append("null");
    }

    /**
     * Writes a JSON boolean.
     * 
     * @param value  the value
     * @throws IOException if an error occurs
     */
    void writeBoolean(boolean value) throws IOException {
        if (value) {
            output.append("true");
        } else {
            output.append("false");
        }
    }

    //-----------------------------------------------------------------------
    /**
     * Writes a JSON int.
     * 
     * @param value  the value
     * @throws IOException if an error occurs
     */
    void writeInt(int value) throws IOException {
        if ((value & 0xfffffff8) == 0) {
            output.append((char) (value + 48));
        } else {
            output.append(Integer.toString(value));
        }
    }

    /**
     * Writes a JSON long.
     * 
     * @param value  the value
     * @throws IOException if an error occurs
     */
    void writeLong(long value) throws IOException {
        output.append(Long.toString(value));
    }

    /**
     * Writes a JSON float.
     * 

* This outputs the values of NaN, and Infinity as strings. * * @param value the value * @throws IOException if an error occurs */ void writeFloat(float value) throws IOException { if (Float.isNaN(value) || Float.isInfinite(value)) { output.append('"').append(Float.toString(value)).append('"'); } else { output.append(Float.toString(value)); } } /** * Writes a JSON double. *

* This outputs the values of NaN, and Infinity as strings. * * @param value the value * @throws IOException if an error occurs */ void writeDouble(double value) throws IOException { if (Double.isNaN(value) || Double.isInfinite(value)) { output.append('"').append(Double.toString(value)).append('"'); } else { output.append(Double.toString(value)); } } //----------------------------------------------------------------------- /** * Writes a JSON string. * * @param value the value * @throws IOException if an error occurs */ void writeString(String value) throws IOException { output.append('"'); for (int i = 0; i < value.length(); i++) { char ch = value.charAt(i); if (ch < 128) { String replace = REPLACE[ch]; if (replace != null) { output.append(replace); } else { output.append(ch); } } else if (ch == '\u2028') { output.append("\\u2028"); // match other JSON writers } else if (ch == '\u2029') { output.append("\\u2029"); // match other JSON writers } else { output.append(ch); } } output.append('"'); } //----------------------------------------------------------------------- /** * Writes a JSON array start. * * @throws IOException if an error occurs */ void writeArrayStart() throws IOException { output.append('['); commaDepth++; commaState.clear(commaDepth); } /** * Writes a JSON array item start. * * @throws IOException if an error occurs */ void writeArrayItemStart() throws IOException { if (commaState.get(commaDepth)) { output.append(','); if (newLine.length() > 0) { output.append(' '); } } else { commaState.set(commaDepth); } } /** * Writes a JSON array end. * * @throws IOException if an error occurs */ void writeArrayEnd() throws IOException { output.append(']'); commaDepth--; } //----------------------------------------------------------------------- /** * Writes a JSON object start. * * @throws IOException if an error occurs */ void writeObjectStart() throws IOException { output.append('{'); currentIndent = currentIndent + indent; commaDepth++; commaState.set(commaDepth, false); } /** * Writes a JSON object key. *

* This handles the comma, string encoded key and separator colon. * * @param key the item key * @throws IOException if an error occurs */ void writeObjectKey(String key) throws IOException { if (commaState.get(commaDepth)) { output.append(','); } else { commaState.set(commaDepth, true); } output.append(newLine); output.append(currentIndent); writeString(key); output.append(':'); if (newLine.length() > 0) { output.append(' '); } } /** * Writes a JSON object key and value. * * @param key the item key * @param value the item value * @throws IOException if an error occurs */ void writeObjectKeyValue(String key, String value) throws IOException { writeObjectKey(key); writeString(value); } /** * Writes a JSON object end. * * @throws IOException if an error occurs */ void writeObjectEnd() throws IOException { currentIndent = currentIndent.substring(0, currentIndent.length() - indent.length()); if (commaState.get(commaDepth)) { output.append(newLine); output.append(currentIndent); } output.append('}'); commaDepth--; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy