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

com.badlogic.gdx.utils.JsonWriter Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright 2011 See AUTHORS file.
 * 
 * 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 com.badlogic.gdx.utils;

import java.io.IOException;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.regex.Pattern;

/** Builder API for emitting JSON to a {@link Writer}.
 * @author Nathan Sweet */
public class JsonWriter extends Writer {
	final Writer writer;
	private final Array stack = new Array();
	private JsonObject current;
	private boolean named;
	private OutputType outputType = OutputType.json;
	private boolean quoteLongValues = false;

	public JsonWriter (Writer writer) {
		this.writer = writer;
	}

	public Writer getWriter () {
		return writer;
	}

	/** Sets the type of JSON output. Default is {@link OutputType#json}. */
	public void setOutputType (OutputType outputType) {
		this.outputType = outputType;
	}

	/** When true, quotes long, double, BigInteger, BigDecimal types to prevent truncation in languages like JavaScript and PHP.
	 * This is not necessary when using libgdx, which handles these types without truncation. Default is false. */
	public void setQuoteLongValues (boolean quoteLongValues) {
		this.quoteLongValues = quoteLongValues;
	}

	public JsonWriter name (String name) throws IOException {
		if (current == null || current.array) throw new IllegalStateException("Current item must be an object.");
		if (!current.needsComma)
			current.needsComma = true;
		else
			writer.write(',');
		writer.write(outputType.quoteName(name));
		writer.write(':');
		named = true;
		return this;
	}

	public JsonWriter object () throws IOException {
		requireCommaOrName();
		stack.add(current = new JsonObject(false));
		return this;
	}

	public JsonWriter array () throws IOException {
		requireCommaOrName();
		stack.add(current = new JsonObject(true));
		return this;
	}

	public JsonWriter value (@Null Object value) throws IOException {
		if (quoteLongValues
			&& (value instanceof Long || value instanceof Double || value instanceof BigDecimal || value instanceof BigInteger)) {
			value = value.toString();
		} else if (value instanceof Number) {
			Number number = (Number)value;
			long longValue = number.longValue();
			if (number.doubleValue() == longValue) value = longValue;
		}
		requireCommaOrName();
		writer.write(outputType.quoteValue(value));
		return this;
	}

	/** Writes the specified JSON value, without quoting or escaping. */
	public JsonWriter json (String json) throws IOException {
		requireCommaOrName();
		writer.write(json);
		return this;
	}

	private void requireCommaOrName () throws IOException {
		if (current == null) return;
		if (current.array) {
			if (!current.needsComma)
				current.needsComma = true;
			else
				writer.write(',');
		} else {
			if (!named) throw new IllegalStateException("Name must be set.");
			named = false;
		}
	}

	public JsonWriter object (String name) throws IOException {
		return name(name).object();
	}

	public JsonWriter array (String name) throws IOException {
		return name(name).array();
	}

	public JsonWriter set (String name, Object value) throws IOException {
		return name(name).value(value);
	}

	/** Writes the specified JSON value, without quoting or escaping. */
	public JsonWriter json (String name, String json) throws IOException {
		return name(name).json(json);
	}

	public JsonWriter pop () throws IOException {
		if (named) throw new IllegalStateException("Expected an object, array, or value since a name was set.");
		stack.pop().close();
		current = stack.size == 0 ? null : stack.peek();
		return this;
	}

	public void write (char[] cbuf, int off, int len) throws IOException {
		writer.write(cbuf, off, len);
	}

	public void flush () throws IOException {
		writer.flush();
	}

	public void close () throws IOException {
		while (stack.size > 0)
			pop();
		writer.close();
	}

	private class JsonObject {
		final boolean array;
		boolean needsComma;

		JsonObject (boolean array) throws IOException {
			this.array = array;
			writer.write(array ? '[' : '{');
		}

		void close () throws IOException {
			writer.write(array ? ']' : '}');
		}
	}

	static public enum OutputType {
		/** Normal JSON, with all its double quotes. */
		json,
		/** Like JSON, but names are only double quoted if necessary. */
		javascript,
		/** Like JSON, but:
		 * 
    *
  • Names only require double quotes if they start with space or any of ":,}/ or they contain * // or /* or :. *
  • Values only require double quotes if they start with space or any of ":,{[]/ or they * contain // or /* or any of }], or they are equal to true, * false , or null. *
  • Newlines are treated as commas, making commas optional in many cases. *
  • C style comments may be used: //... or /*...*/ *
*/ minimal; static private Pattern javascriptPattern = Pattern.compile("^[a-zA-Z_$][a-zA-Z_$0-9]*$"); static private Pattern minimalNamePattern = Pattern.compile("^[^\":,}/ ][^:]*$"); static private Pattern minimalValuePattern = Pattern.compile("^[^\":,{\\[\\]/ ][^}\\],]*$"); public String quoteValue (@Null Object value) { if (value == null) return "null"; String string = value.toString(); if (value instanceof Number || value instanceof Boolean) return string; StringBuilder buffer = new StringBuilder(string); buffer.replace('\\', "\\\\").replace('\r', "\\r").replace('\n', "\\n").replace('\t', "\\t"); if (this == OutputType.minimal && !string.equals("true") && !string.equals("false") && !string.equals("null") && !string.contains("//") && !string.contains("/*")) { int length = buffer.length(); if (length > 0 && buffer.charAt(length - 1) != ' ' && minimalValuePattern.matcher(buffer).matches()) return buffer.toString(); } return '"' + buffer.replace('"', "\\\"").toString() + '"'; } public String quoteName (String value) { StringBuilder buffer = new StringBuilder(value); buffer.replace('\\', "\\\\").replace('\r', "\\r").replace('\n', "\\n").replace('\t', "\\t"); switch (this) { case minimal: if (!value.contains("//") && !value.contains("/*") && minimalNamePattern.matcher(buffer).matches()) return buffer.toString(); case javascript: if (javascriptPattern.matcher(buffer).matches()) return buffer.toString(); } return '"' + buffer.replace('"', "\\\"").toString() + '"'; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy