Package org.apache.pivot.json

Source Code of org.apache.pivot.json.JSONSerializer

/*
* 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.pivot.json;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.Charset;

import org.apache.pivot.beans.BeanAdapter;
import org.apache.pivot.collections.ArrayList;
import org.apache.pivot.collections.Dictionary;
import org.apache.pivot.collections.HashMap;
import org.apache.pivot.collections.List;
import org.apache.pivot.collections.Map;
import org.apache.pivot.collections.Sequence;
import org.apache.pivot.io.EchoReader;
import org.apache.pivot.io.EchoWriter;
import org.apache.pivot.serialization.SerializationException;
import org.apache.pivot.serialization.Serializer;

/**
* Implementation of the {@link Serializer} interface that reads data from
* and writes data to a JavaScript Object Notation (JSON) file.
*/
public class JSONSerializer implements Serializer<Object> {
    private Charset charset;
    private Class<?> type;

    private int c = -1;
    private boolean alwaysDelimitMapKeys = false;
    private boolean verbose = false;

    public static final String DEFAULT_CHARSET_NAME = "UTF-8";
    public static final String MIME_TYPE = "application/json";
    public static final int BUFFER_SIZE = 2048;

    public JSONSerializer() {
        this(Charset.forName(DEFAULT_CHARSET_NAME), Object.class);
    }

    public JSONSerializer(Charset charset) {
        this(charset, Object.class);
    }

    public JSONSerializer(Class<?> type) {
        this(Charset.forName(DEFAULT_CHARSET_NAME), type);
    }

    public JSONSerializer(Charset charset, Class<?> type) {
        if (charset == null) {
            throw new IllegalArgumentException("charset is null.");
        }

        this.charset = charset;
        this.type = type;
    }

    /**
     * Returns the character set used to encode/decode the JSON data.
     */
    public Charset getCharset() {
        return charset;
    }

    /**
     * Returns the type of the object that will be returned by {@link #readObject(Reader)}.
     */
    public Class<?> getType() {
        return type;
    }

    /**
     * Returns a flag indicating whether or not map keys will always be
     * quote-delimited.
     */
    public boolean getAlwaysDelimitMapKeys() {
        return alwaysDelimitMapKeys;
    }

    /**
     * Sets a flag indicating that map keys should always be quote-delimited.
     *
     * @param alwaysDelimitMapKeys
     * <tt>true</tt> to bound map keys in double quotes; <tt>false</tt> to
     * only quote-delimit keys as necessary.
     */
    public void setAlwaysDelimitMapKeys(boolean alwaysDelimitMapKeys) {
        this.alwaysDelimitMapKeys = alwaysDelimitMapKeys;
    }

    /**
     * Returns the serializer's verbosity flag.
     */
    public boolean isVerbose() {
        return verbose;
    }

    /**
     * Sets the serializer's verbosity flag. When verbosity is enabled, all data read or
     * written will be echoed to the console.
     *
     * @param verbose
     */
    public void setVerbose(boolean verbose) {
        this.verbose = verbose;
    }

    /**
     * Reads data from a JSON stream.
     *
     * @param inputStream
     * The input stream from which data will be read.
     *
     * @see #readObject(Reader)
     */
    @Override
    public Object readObject(InputStream inputStream)
        throws IOException, SerializationException {
        if (inputStream == null) {
            throw new IllegalArgumentException("inputStream is null.");
        }

        Reader reader = new BufferedReader(new InputStreamReader(inputStream, charset), BUFFER_SIZE);
        if (verbose) {
            reader = new EchoReader(reader);
        }

        return readObject(reader);
    }

    /**
     * Reads data from a JSON stream.
     *
     * @param reader
     * The reader from which data will be read.
     *
     * @return
     * One of the following types, depending on the content of the stream:
     *
     * <ul>
     * <li>java.lang.String</li>
     * <li>java.lang.Number</li>
     * <li>java.lang.Boolean</li>
     * <li>pivot.collections.List</li>
     * <li>pivot.collections.Map</li>
     * </ul>
     */
    public Object readObject(Reader reader)
        throws IOException, SerializationException {
        if (reader == null) {
            throw new IllegalArgumentException("reader is null.");
        }

        // Move to the first character
        c = reader.read();

        // Ignore BOM (if present)
        if (c == 0xFEFF) {
            c = reader.read();
        }

        // Read the root value
        LineNumberReader lineNumberReader = new LineNumberReader(reader);
        Object object;

        try {
            object = readValue(lineNumberReader, type);
        } catch (SerializationException exception) {
            System.err.println("An error occurred while processing input at line number "
                + (lineNumberReader.getLineNumber() + 1));

            throw exception;
        }

        return object;
    }

    private Object readValue(Reader reader, Type type)
        throws IOException, SerializationException {
        Object object = null;

        skipWhitespaceAndComments(reader);

        if (c == -1) {
            throw new SerializationException("Unexpected end of input stream.");
        }

        if (c == 'n') {
            object = readNull(reader);
        } else if (c == '"' || c == '\'') {
            object = readString(reader, type);
        } else if (c == '+' || c == '-' || Character.isDigit(c)) {
            object = readNumber(reader, type);
        } else if (c == 't' || c == 'f') {
            object = readBoolean(reader, type);
        } else if (c == '[') {
            object = readList(reader, type);
        } else if (c == '{') {
            object = readMap(reader, type);
        } else {
            throw new SerializationException("Unexpected character in input stream.");
        }

        return object;
    }

    private void skipWhitespaceAndComments(Reader reader)
        throws IOException, SerializationException {
        while (c != -1
            && (Character.isWhitespace(c)
                || c == '/')) {
            boolean comment = (c == '/');

            // Read the next character
            c = reader.read();

            if (comment) {
                if (c == '/') {
                    // Single-line comment
                    while (c != -1
                        && c != '\n'
                        && c != '\r') {
                        c = reader.read();
                    }
                } else if (c == '*') {
                    // Multi-line comment
                    boolean closed = false;

                    while (c != -1
                        && !closed) {
                        c = reader.read();

                        if (c == '*') {
                            c = reader.read();
                            closed = (c == '/');
                        }
                    }

                    if (!closed) {
                        throw new SerializationException("Unexpected end of input stream.");
                    }

                    if (c != -1) {
                        c = reader.read();
                    }
                } else {
                    throw new SerializationException("Unexpected character in input stream.");
                }
            }
        }
    }

    private Object readNull(Reader reader)
        throws IOException, SerializationException {
        String nullString = "null";

        int n = nullString.length();
        int i = 0;

        while (c != -1 && i < n) {
            if (nullString.charAt(i) != c) {
                throw new SerializationException("Unexpected character in input stream.");
            }

            c = reader.read();
            i++;
        }

        if (i < n) {
            throw new SerializationException("Incomplete null value in input stream.");
        }

        return null;
    }

    private Object readString(Reader reader, Type type)
        throws IOException, SerializationException {
        if (!(type instanceof Class<?>)) {
            throw new SerializationException("Cannot convert string to " + type + ".");
        }

        StringBuilder stringBuilder = new StringBuilder();

        // Use the same delimiter to close the string
        int t = c;

        // Move to the next character after the delimiter
        c = reader.read();

        while (c != -1 && c != t) {
            if (!Character.isISOControl(c)) {
                if (c == '\\') {
                    c = reader.read();

                    if (c == 'b') {
                        c = '\b';
                    } else if (c == 'f') {
                        c = '\f';
                    } else if (c == 'n') {
                        c = '\n';
                    } else if (c == 'r') {
                        c = '\r';
                    } else if (c == 't') {
                        c = '\t';
                    } else if (c == 'u') {
                        StringBuilder unicodeBuilder = new StringBuilder();
                        while (unicodeBuilder.length() < 4) {
                            c = reader.read();
                            unicodeBuilder.append((char)c);
                        }

                        String unicode = unicodeBuilder.toString();
                        c = (char)Integer.parseInt(unicode, 16);
                    } else {
                        if (!(c == '\\'
                            || c == '/'
                            || c == '\"'
                            || c == '\''
                            || c == t)) {
                            throw new SerializationException("Unsupported escape sequence in input stream.");
                        }
                    }
                }

                stringBuilder.append((char)c);
            }

            c = reader.read();
        }

        if (c != t) {
            throw new SerializationException("Unterminated string in input stream.");
        }

        // Move to the next character after the delimiter
        c = reader.read();

        return BeanAdapter.coerce(stringBuilder.toString(), (Class<?>)type);
    }

    private Object readNumber(Reader reader, Type type)
        throws IOException, SerializationException {
        if (!(type instanceof Class<?>)) {
            throw new SerializationException("Cannot convert number to " + type + ".");
        }

        Number number = null;

        StringBuilder stringBuilder = new StringBuilder();
        boolean negative = false;
        boolean integer = true;

        if (c == '+' || c == '-') {
            negative = (c == '-');
            c = reader.read();
        }

        while (c != -1 && (Character.isDigit(c) || c == '.'
            || c == 'e' || c == 'E')) {
            stringBuilder.append((char)c);
            integer &= !(c == '.');
            c = reader.read();
        }

        if (integer) {
            // TODO 5/28/2008 Remove 32-bit optimization when 64-bit processors
            // are more prevalent
            long value = Long.parseLong(stringBuilder.toString()) * (negative ? -1 : 1);

            if (value > Integer.MAX_VALUE
                || value < Integer.MIN_VALUE) {
                number = value;
            } else {
                number = (int)value;
            }
        } else {
            number = Double.parseDouble(stringBuilder.toString()) * (negative ? -1.0d : 1.0d);
        }

        return BeanAdapter.coerce(number, (Class<?>)type);
    }

    private Object readBoolean(Reader reader, Type type)
        throws IOException, SerializationException {
        if (!(type instanceof Class<?>)) {
            throw new SerializationException("Cannot convert number to " + type + ".");
        }

        String text = (c == 't') ? "true" : "false";
        int n = text.length();
        int i = 0;

        while (c != -1 && i < n) {
            if (text.charAt(i) != c) {
                throw new SerializationException("Unexpected character in input stream.");
            }

            c = reader.read();
            i++;
        }

        if (i < n) {
            throw new SerializationException("Incomplete boolean value in input stream.");
        }

        return BeanAdapter.coerce(Boolean.parseBoolean(text), (Class<?>)type);
    }

    @SuppressWarnings("unchecked")
    private Object readList(Reader reader, Type type)
        throws IOException, SerializationException {
        Sequence<Object> sequence;
        Type itemType;

        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType)type;
            Class<?> rawType = (Class<?>)parameterizedType.getRawType();
            if (!Sequence.class.isAssignableFrom(rawType)) {
                throw new IllegalArgumentException("Cannot convert array to "
                    + rawType.getName() + ".");
            }

            try {
                sequence = (Sequence<Object>)rawType.newInstance();
            } catch (InstantiationException exception) {
                throw new RuntimeException(exception);
            } catch (IllegalAccessException exception) {
                throw new RuntimeException(exception);
            }

            // Get the target item type
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            itemType = actualTypeArguments[0];
        } else if (type == Object.class) {
            sequence = new ArrayList<Object>();
            itemType = Object.class;
        } else {
            throw new IllegalArgumentException("Cannot convert array to " + type + ".");
        }

        // Move to the next character after '['
        c = reader.read();
        skipWhitespaceAndComments(reader);

        while (c != -1 && c != ']') {
            sequence.add(readValue(reader, itemType));
            skipWhitespaceAndComments(reader);

            if (c == ',') {
                c = reader.read();
                skipWhitespaceAndComments(reader);
            } else if (c == -1) {
                throw new SerializationException("Unexpected end of input stream.");
            } else {
                if (c != ']') {
                    throw new SerializationException("Unexpected character in input stream.");
                }
            }
        }

        // Move to the next character after ']'
        c = reader.read();

        return sequence;
    }

    @SuppressWarnings("unchecked")
    private Object readMap(Reader reader, Type type)
        throws IOException, SerializationException {
        Dictionary<String, Object> dictionary;
        Type valueType;

        if (type instanceof ParameterizedType) {
            // Instantiate the target dictionary
            ParameterizedType parameterizedType = (ParameterizedType)type;
            Class<?> rawType = (Class<?>)parameterizedType.getRawType();
            if (!Dictionary.class.isAssignableFrom(rawType)) {
                throw new IllegalArgumentException("Cannot convert object to "
                    + rawType.getName() + ".");
            }

            try {
                dictionary = (Dictionary<String, Object>)rawType.newInstance();
            } catch (InstantiationException exception) {
                throw new RuntimeException(exception);
            } catch (IllegalAccessException exception) {
                throw new RuntimeException(exception);
            }

            // Get the target value type
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            valueType = actualTypeArguments[1];
        } else if (type == Object.class){
            dictionary = new HashMap<String, Object>();
            valueType = Object.class;
        } else {
            Class<?> beanType = (Class<?>)type;
            try {
                dictionary = new BeanAdapter(beanType.newInstance());
            } catch (InstantiationException exception) {
                throw new RuntimeException(exception);
            } catch (IllegalAccessException exception) {
                throw new RuntimeException(exception);
            }

            valueType = null;
        }

        // Move to the next character after '{'
        c = reader.read();
        skipWhitespaceAndComments(reader);

        while (c != -1 && c != '}') {
            String key = null;

            if (c == '"' || c == '\'') {
                // The key is a delimited string
                key = (String)readString(reader, String.class);
            } else {
                // The key is an undelimited string; it must adhere to Java
                // identifier syntax
                StringBuilder keyStringBuilder = new StringBuilder();

                if (!Character.isJavaIdentifierStart(c)) {
                    throw new SerializationException("Illegal identifier start character.");
                }

                while (c != -1
                    && c != ':' && !Character.isWhitespace(c)) {
                    if (!Character.isJavaIdentifierPart(c)) {
                        throw new SerializationException("Illegal identifier character.");
                    }

                    keyStringBuilder.append((char)c);
                    c = reader.read();
                }

                if (c == -1) {
                    throw new SerializationException("Unexpected end of input stream.");
                }

                key = keyStringBuilder.toString();
            }

            if (key == null
                || key.length() == 0) {
                throw new SerializationException("\"" + key + "\" is not a valid key.");
            }

            skipWhitespaceAndComments(reader);

            if (c != ':') {
                throw new SerializationException("Unexpected character in input stream.");
            }

            // Move to the first character after ':'
            c = reader.read();
            dictionary.put(key, readValue(reader, (valueType == null) ?
                ((BeanAdapter)dictionary).getGenericType(key) : valueType));

            skipWhitespaceAndComments(reader);

            if (c == ',') {
                c = reader.read();
                skipWhitespaceAndComments(reader);
            } else if (c == -1) {
                throw new SerializationException("Unexpected end of input stream.");
            } else {
                if (c != '}') {
                    throw new SerializationException("Unexpected character in input stream.");
                }
            }
        }

        // Move to the first character after '}'
        c = reader.read();

        return (dictionary instanceof BeanAdapter) ? ((BeanAdapter)dictionary).getBean() : dictionary;
    }

    /**
     * Writes data to a JSON stream.
     *
     * @param object
     *
     * @param outputStream
     * The output stream to which data will be written.
     *
     * @see #writeObject(Object, Writer)
     */
    @Override
    public void writeObject(Object object, OutputStream outputStream)
        throws IOException, SerializationException {
        if (outputStream == null) {
            throw new IllegalArgumentException("outputStream is null.");
        }

        Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream, charset), BUFFER_SIZE);
        if (verbose) {
            writer = new EchoWriter(writer);
        }

        writeObject(object, writer);
    }

    /**
     * Writes data to a JSON stream.
     *
     * @param object
     * The object to serialize. Must be one of the following types:
     *
     * <ul>
     * <li>java.lang.String</li>
     * <li>java.lang.Number</li>
     * <li>java.lang.Boolean</li>
     * <li>pivot.collections.List</li>
     * <li>pivot.collections.Map</li>
     * </ul>
     *
     * @param writer
     * The writer to which data will be written.
     */
    @SuppressWarnings("unchecked")
    public void writeObject(Object object, Writer writer)
        throws IOException, SerializationException {
        if (writer == null) {
            throw new IllegalArgumentException("writer is null.");
        }

        if (object == null) {
            writer.append("null");
        } else if (object instanceof String) {
            String string = (String)object;
            StringBuilder stringBuilder = new StringBuilder();

            for (int i = 0, n = string.length(); i < n; i++) {
                char c = string.charAt(i);

                switch(c) {
                    case '\t': {
                        stringBuilder.append("\\t");
                        break;
                    }

                    case '\n': {
                        stringBuilder.append("\\n");
                        break;
                    }

                    case '\\':
                    case '\"':
                    case '\'': {
                        stringBuilder.append("\\" + c);
                        break;
                    }

                    default: {
                        if (charset.name().startsWith("UTF")
                            || c <= 0xFF) {
                            stringBuilder.append(c);
                        } else {
                            stringBuilder.append("\\u");
                            stringBuilder.append(String.format("%04x", (short)c));
                        }
                    }
                }

            }

            writer.append("\"" + stringBuilder.toString() + "\"");
        } else if (object instanceof Number) {
            Number number = (Number)object;

            if (number instanceof Float) {
                Float f = (Float)number;
                if (f.isNaN()
                    || f.isInfinite()) {
                    throw new SerializationException(number + " is not a valid value.");
                }
            } else if (number instanceof Double) {
                Double d = (Double)number;
                if (d.isNaN()
                    || d.isInfinite()) {
                    throw new SerializationException(number + " is not a valid value.");
                }
            }

            writer.append(number.toString());
        } else if (object instanceof Boolean) {
            writer.append(object.toString());
        } else if (object instanceof List<?>) {
            List<Object> list = (List<Object>)object;
            writer.append("[");

            int i = 0;
            for (Object item : list) {
                if (i > 0) {
                    writer.append(", ");
                }

                writeObject(item, writer);
                i++;
            }

            writer.append("]");
        } else {
            Map<String, Object> map;
            if (object instanceof Map<?, ?>) {
                map = (Map<String, Object>)object;
            } else {
                map = new BeanAdapter(object);
            }

            writer.append("{");

            int i = 0;
            for (String key : map) {
                Object value = map.get(key);

                boolean identifier = true;
                StringBuilder keyStringBuilder = new StringBuilder();

                for (int j = 0, n = key.length(); j < n; j++) {
                    char c = key.charAt(j);
                    identifier &= Character.isJavaIdentifierPart(c);

                    if (c == '"') {
                        keyStringBuilder.append('\\');
                    }

                    keyStringBuilder.append(c);
                }

                key = keyStringBuilder.toString();

                if (i > 0) {
                    writer.append(", ");
                }

                // Write the key
                if (!identifier || alwaysDelimitMapKeys) {
                    writer.append('"');
                }

                writer.append(key);

                if (!identifier || alwaysDelimitMapKeys) {
                    writer.append('"');
                }

                writer.append(": ");

                // Write the value
                writeObject(value, writer);

                i++;
            }

            writer.append("}");
        }

        writer.flush();
    }

    @Override
    public String getMIMEType(Object object) {
        return MIME_TYPE + "; charset=" + charset.name();
    }

    /**
     * Converts a JSON value to a Java object.
     *
     * @param json
     * The JSON value.
     *
     * @return
     * The parsed object.
     */
    public static Object parse(String json) throws SerializationException {
        JSONSerializer jsonSerializer = new JSONSerializer();

        Object object;
        try {
            object = jsonSerializer.readObject(new StringReader(json));
        } catch(IOException exception) {
            throw new RuntimeException(exception);
        }

        return object;
    }

    /**
     * Converts a JSON value to a string.
     *
     * @param json
     * The JSON value.
     *
     * @return
     * The parsed string.
     */
    public static String parseString(String json) throws SerializationException {
        return (String)parse(json);
    }

    /**
     * Converts a JSON value to a number.
     *
     * @param json
     * The JSON value.
     *
     * @return
     * The parsed number.
     */
    public static Number parseNumber(String json) throws SerializationException {
        return (Number)parse(json);
    }

    /**
     * Converts a JSON value to a short.
     *
     * @param json
     * The JSON value.
     *
     * @return
     * The parsed short.
     */
    public static Short parseShort(String json) throws SerializationException {
        return (Short)parse(json);
    }

    /**
     * Converts a JSON value to a integer.
     *
     * @param json
     * The JSON value.
     *
     * @return
     * The parsed integer.
     */
    public static Integer parseInteger(String json) throws SerializationException {
        return (Integer)parse(json);
    }

    /**
     * Converts a JSON value to a long.
     *
     * @param json
     * The JSON value.
     *
     * @return
     * The parsed number.
     */
    public static Long parseLong(String json) throws SerializationException {
        return (Long)parse(json);
    }

    /**
     * Converts a JSON value to a float.
     *
     * @param json
     * The JSON value.
     *
     * @return
     * The parsed float.
     */
    public static Float parseFloat(String json) throws SerializationException {
        return (Float)parse(json);
    }

    /**
     * Converts a JSON value to a double.
     *
     * @param json
     * The JSON value.
     *
     * @return
     * The parsed double.
     */
    public static Double parseDouble(String json) throws SerializationException {
        return (Double)parse(json);
    }

    /**
     * Converts a JSON value to a boolean.
     *
     * @param json
     * The JSON value.
     *
     * @return
     * The parsed boolean.
     */
    public static Boolean parseBoolean(String json) throws SerializationException {
        return (Boolean)parse(json);
    }

    /**
     * Converts a JSON value to a list.
     *
     * @param json
     * The JSON value.
     *
     * @return
     * The parsed list.
     */
    public static List<?> parseList(String json) throws SerializationException {
        return (List<?>)parse(json);
    }

    /**
     * Converts a JSON value to a map.
     *
     * @param json
     * The JSON value.
     *
     * @return
     * The parsed map.
     */
    @SuppressWarnings("unchecked")
    public static Map<String, ?> parseMap(String json) throws SerializationException {
        return (Map<String, ?>)parse(json);
    }

    /**
     * Converts a object to a JSON string representation.
     *
     * @param value
     * The object to convert.
     *
     * @return
     * The resulting JSON string.
     */
    public static String toString(Object value) throws SerializationException {
        JSONSerializer jsonSerializer = new JSONSerializer();
        StringWriter writer = new StringWriter();

        try {
            jsonSerializer.writeObject(value, writer);
        } catch(IOException exception) {
            throw new RuntimeException(exception);
        }

        return writer.toString();
    }

    /**
     * Converts a string to a JSON string representation.
     *
     * @param value
     * The object to convert.
     *
     * @return
     * The resulting JSON string.
     */
    public static String toString(String value) {
        try {
            return toString((Object)value);
        } catch(SerializationException exception) {
            throw new RuntimeException(exception);
        }
    }

    /**
     * Converts a number to a JSON string representation.
     *
     * @param value
     * The object to convert.
     *
     * @return
     * The resulting JSON string.
     */
    public static String toString(Number value) {
        try {
            return toString((Object)value);
        } catch(SerializationException exception) {
            throw new RuntimeException(exception);
        }
    }

    /**
     * Converts a boolean to a JSON string representation.
     *
     * @param value
     * The object to convert.
     *
     * @return
     * The resulting JSON string.
     */
    public static String toString(Boolean value) {
        try {
            return toString((Object)value);
        } catch(SerializationException exception) {
            throw new RuntimeException(exception);
        }
    }

    /**
     * Converts a list to a JSON string representation.
     *
     * @param value
     * The object to convert.
     *
     * @return
     * The resulting JSON string.
     */
    public static String toString(List<?> value) {
        try {
            return toString((Object)value);
        } catch(SerializationException exception) {
            throw new RuntimeException(exception);
        }
    }

    /**
     * Converts a map to a JSON string representation.
     *
     * @param value
     * The object to convert.
     *
     * @return
     * The resulting JSON string.
     */
    public static String toString(Map<String, ?> value) {
        try {
            return toString((Object)value);
        } catch(SerializationException exception) {
            throw new RuntimeException(exception);
        }
    }
}
TOP

Related Classes of org.apache.pivot.json.JSONSerializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.