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

grails.plugin.json.builder.JsonOutput Maven / Gradle / Ivy

package grails.plugin.json.builder;
/*
 *  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.
 */

import groovy.json.JsonException;
import groovy.json.JsonLexer;
import groovy.json.JsonToken;
import groovy.lang.Closure;
import groovy.lang.Writable;
import groovy.util.Expando;
import org.apache.groovy.json.internal.CharBuf;
import org.apache.groovy.json.internal.Chr;
import org.grails.buffer.FastStringWriter;

import javax.validation.constraints.NotNull;
import java.io.*;
import java.net.URL;
import java.util.*;

/**
 * Temporary fork of {@link groovy.json.JsonOutput} until Groovy 2.5.0 is out.
 *
 * 

Class responsible for the actual String serialization of the possible values of a JSON structure. * This class can also be used as a category, to add toJson() methods to various types. * * @author Guillaume Laforge * @author Roshan Dawrani * @author Andrey Bloschetsov * @author Rick Hightower * @author Graeme Rocher * * @since 1.8.0 */ public class JsonOutput { public static final char OPEN_BRACKET = '['; public static final char CLOSE_BRACKET = ']'; public static final char OPEN_BRACE = '{'; public static final char CLOSE_BRACE = '}'; public static final char COLON = ':'; public static final char COMMA = ','; public static final char SPACE = ' '; public static final char NEW_LINE = '\n'; public static final char QUOTE = '"'; public static final String NULL_VALUE = "null"; public static final String JSON_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; public static final String DEFAULT_TIMEZONE = "GMT"; static final char[] EMPTY_STRING_CHARS = Chr.array(QUOTE, QUOTE); static final char[] EMPTY_MAP_CHARS = {OPEN_BRACE, CLOSE_BRACE}; static final char[] EMPTY_LIST_CHARS = {OPEN_BRACKET, CLOSE_BRACKET}; static final JsonGenerator DEFAULT_GENERATOR; static { JsonGenerator.Options options = new JsonGenerator.Options() .disableUnicodeEscaping() .dateFormat(JSON_DATE_FORMAT) .timezone(DEFAULT_TIMEZONE); DEFAULT_GENERATOR = new DefaultJsonGenerator(options); } /** * @param bool a {@link Boolean} * @return "true" or "false" for a boolean value */ public static String toJson(Boolean bool) { return DEFAULT_GENERATOR.toJson(bool); } /** * @param n a {@link Number} to write as JSON string * @return a string representation for a number * @throws groovy.json.JsonException * If the number is infinite or not a number */ public static String toJson(Number n) { return DEFAULT_GENERATOR.toJson(n); } /** * @param c a {@link Character} * @return a JSON string representation of the character */ public static String toJson(Character c) { return DEFAULT_GENERATOR.toJson(c); } /** * @param s a {@link String} to be represented in JSON * @return a properly encoded string with escape sequences */ public static String toJson(String s) { return DEFAULT_GENERATOR.toJson(s); } /** * Format a date that is parseable from JavaScript, according to ISO-8601. * * @param date the date to format to a JSON string * @return a formatted date in the form of a string */ public static String toJson(Date date) { return DEFAULT_GENERATOR.toJson(date); } /** * Format a calendar instance that is parseable from JavaScript, according to ISO-8601. * * @param cal the calendar to format to a JSON string * @return a formatted date in the form of a string */ public static String toJson(Calendar cal) { return DEFAULT_GENERATOR.toJson(cal); } /** * @param uuid a {@link UUID} * @return the string representation of an uuid */ public static String toJson(UUID uuid) { return DEFAULT_GENERATOR.toJson(uuid); } /** * @param url a {@link URL} * @return the string representation of the URL */ public static String toJson(URL url) { return DEFAULT_GENERATOR.toJson(url); } /** * @param closure a {@link Closure} to format to JSON string * @return an object representation of a closure */ public static String toJson(Closure closure) { return DEFAULT_GENERATOR.toJson(closure); } /** * @param expando a {@link Expando} object to format to JSON string * @return an object representation of an Expando */ public static String toJson(Expando expando) { return DEFAULT_GENERATOR.toJson(expando); } /** * @param object an {@link Object} to format to JSON string * @return "null" for a null value, or a JSON array representation for a collection, array, iterator or enumeration, * or representation for other object. */ public static String toJson(Object object) { return DEFAULT_GENERATOR.toJson(object); } /** * @param m a {@link Map} to format to JSON string * @return a JSON object representation for a map */ public static String toJson(Map m) { return DEFAULT_GENERATOR.toJson(m); } /** * Pretty print a JSON payload. * * @param jsonPayload a JSON payload * @return a pretty representation of JSON payload. */ public static String prettyPrint(String jsonPayload) { int indentSize = 0; // Just a guess that the pretty view will take a 20 percent more than original. final CharBuf output = CharBuf.create((int) (jsonPayload.length() * 1.2)); JsonLexer lexer = new JsonLexer(new StringReader(jsonPayload)); // Will store already created indents. Map indentCache = new HashMap<>(); while (lexer.hasNext()) { JsonToken token = lexer.next(); switch (token.getType()) { case OPEN_CURLY: indentSize += 4; output.addChars(Chr.array(OPEN_BRACE, NEW_LINE)).addChars(getIndent(indentSize, indentCache)); break; case CLOSE_CURLY: indentSize -= 4; output.addChar(NEW_LINE); if (indentSize > 0) { output.addChars(getIndent(indentSize, indentCache)); } output.addChar(CLOSE_BRACE); break; case OPEN_BRACKET: indentSize += 4; output.addChars(Chr.array(OPEN_BRACKET, NEW_LINE)).addChars(getIndent(indentSize, indentCache)); break; case CLOSE_BRACKET: indentSize -= 4; output.addChar(NEW_LINE); if (indentSize > 0) { output.addChars(getIndent(indentSize, indentCache)); } output.addChar(CLOSE_BRACKET); break; case COMMA: output.addChars(Chr.array(COMMA, NEW_LINE)).addChars(getIndent(indentSize, indentCache)); break; case COLON: output.addChars(Chr.array(COLON, SPACE)); break; case STRING: String textStr = token.getText(); String textWithoutQuotes = textStr.substring(1, textStr.length() - 1); if (!textWithoutQuotes.isEmpty()) { output.addJsonEscapedString(textWithoutQuotes); } else { output.addQuoted(Chr.array()); } break; default: output.addString(token.getText()); } } return output.toString(); } /** * Creates new indent if it not exists in the indent cache. * * @return indent with the specified size. */ private static char[] getIndent(int indentSize, Map indentCache) { char[] indent = indentCache.get(indentSize); if (indent == null) { indent = new char[indentSize]; Arrays.fill(indent, SPACE); indentCache.put(indentSize, indent); } return indent; } /** * Obtains JSON unescaped text for the given text * * @param text The text * @return The unescaped text */ public static JsonUnescaped unescaped(CharSequence text) { return new JsonUnescaped(text); } /** * Represents unescaped JSON */ public static class JsonUnescaped { private final CharSequence text; public JsonUnescaped(CharSequence text) { this.text = text; } public CharSequence getText() { return text; } @Override public String toString() { return text.toString(); } } /** * Represents unescaped JSON */ public static abstract class JsonWritable implements Writable, CharSequence { protected boolean inline = false; protected boolean first = true; public void setInline(boolean inline) { this.inline = inline; } public void setFirst(boolean first) { this.first = first; } @Override public String toString() { FastStringWriter out = new FastStringWriter(); try { writeTo(out); } catch (IOException e) { throw new JsonException("Error writing JSON writable: " + e.getMessage(), e); } return out.toString(); } @Override public int length() { return toString().length(); } @Override public char charAt(int index) { return toString().charAt(index); } @Override public CharSequence subSequence(int start, int end) { return toString().subSequence(start, end); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy