com.google.gwt.core.client.JsonUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.core.client.JsonUtils.java

Source

/*
 * Copyright 2009 Google Inc.
 * 
 * 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.google.gwt.core.client;

/**
 * Provides JSON-related utility methods.
 */
public class JsonUtils {
    private static JavaScriptObject escapeTable = initEscapeTable();

    private static final boolean hasJsonParse = hasJsonParse();

    /**
     * Escapes characters within a JSON string than cannot be passed directly to
     * eval(). Control characters, quotes and backslashes are not affected.
     */
    public static native String escapeJsonForEval(String toEscape) /*-{
                                                                   var s = toEscape.replace(/[\xad\u0600-\u0603\u06dd\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202e\u2060-\u2063\u206a-\u206f\ufeff\ufff9-\ufffb]/g, function(x) {
                                                                   return @com.google.gwt.core.client.JsonUtils::escapeChar(Ljava/lang/String;)(x);
                                                                   });
                                                                   return s;
                                                                   }-*/;

    /**
     * Returns a quoted, escaped JSON String.
     */
    public static native String escapeValue(String toEscape) /*-{
                                                             var s = toEscape.replace(/[\x00-\x1f\xad\u0600-\u0603\u06dd\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202e\u2060-\u2063\u206a-\u206f\ufeff\ufff9-\ufffb"\\]/g, function(x) {
                                                             return @com.google.gwt.core.client.JsonUtils::escapeChar(Ljava/lang/String;)(x);
                                                             });
                                                             return "\"" + s + "\"";
                                                             }-*/;

    /**
     * Evaluates a JSON expression safely. The payload must evaluate to an Object
     * or an Array (not a primitive or a String).
     * 
     * @param <T> The type of JavaScriptObject that should be returned
     * @param json The source JSON text
     * @return The evaluated object
     * 
     * @throws IllegalArgumentException if the input is not valid JSON
     */
    public static native <T extends JavaScriptObject> T safeEval(String json) /*-{
                                                                              var v;
                                                                              if (@com.google.gwt.core.client.JsonUtils::hasJsonParse) {
                                                                              try {
                                                                              return JSON.parse(json);
                                                                              } catch (e) {
                                                                              return @com.google.gwt.core.client.JsonUtils::throwIllegalArgumentException(*)("Error parsing JSON: " + e, json);
                                                                              }
                                                                              } else {
                                                                              if (!@com.google.gwt.core.client.JsonUtils::safeToEval(Ljava/lang/String;)(json)) {
                                                                              return @com.google.gwt.core.client.JsonUtils::throwIllegalArgumentException(*)("Illegal character in JSON string", json);
                                                                              }
                                                                              json = @com.google.gwt.core.client.JsonUtils::escapeJsonForEval(Ljava/lang/String;)(json);
                                                                              try {
                                                                              return eval('(' + json + ')');
                                                                              } catch (e) {
                                                                              return @com.google.gwt.core.client.JsonUtils::throwIllegalArgumentException(*)("Error parsing JSON: " + e, json);
                                                                              }
                                                                              }
                                                                              }-*/;

    /**
     * Returns true if the given JSON string may be safely evaluated by {@code
     * eval()} without undersired side effects or security risks. Note that a true
     * result from this method does not guarantee that the input string is valid
     * JSON.  This method does not consider the contents of quoted strings; it
     * may still be necessary to perform escaping prior to evaluation for correct
     * results.
     * 
     * <p> The technique used is taken from <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>.
     */
    public static native boolean safeToEval(String text) /*-{
                                                         // Remove quoted strings and disallow anything except:
                                                         //
                                                         // 1) symbols and brackets ,:{}[]
                                                         // 2) numbers: digits 0-9, ., -, +, e, and E
                                                         // 3) literal values: 'null', 'true' and 'false' = [aeflnr-u]
                                                         // 4) whitespace: ' ', '\n', '\r', and '\t'
                                                         return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(text.replace(/"(\\.|[^"\\])*"/g, '')));
                                                         }-*/;

    /**
     * Evaluates a JSON expression using {@code eval()}. This method does not
     * validate the JSON text and should only be used on JSON from trusted
     * sources. The payload must evaluate to an Object or an Array (not a
     * primitive or a String).
     * 
     * @param <T> The type of JavaScriptObject that should be returned
     * @param json The source JSON text
     * @return The evaluated object
     */
    public static native <T extends JavaScriptObject> T unsafeEval(String json) /*-{
                                                                                var escaped = @com.google.gwt.core.client.JsonUtils::escapeJsonForEval(Ljava/lang/String;)(json);
                                                                                try {
                                                                                return eval('(' + escaped + ')');
                                                                                } catch (e) {
                                                                                return @com.google.gwt.core.client.JsonUtils::throwIllegalArgumentException(*)("Error parsing JSON: " + e, json);
                                                                                }
                                                                                }-*/;

    static void throwIllegalArgumentException(String message, String data) {
        throw new IllegalArgumentException(message + "\n" + data);
    }

    private static native String escapeChar(String c) /*-{
                                                      var lookedUp = @com.google.gwt.core.client.JsonUtils::escapeTable[c.charCodeAt(0)];
                                                      return (lookedUp == null) ? c : lookedUp;
                                                      }-*/;

    /**
     * Returns true if the JSON.parse function is present, false otherwise.
     */
    private static native boolean hasJsonParse() /*-{
                                                 return typeof JSON == "object" && typeof JSON.parse == "function";
                                                 }-*/;

    private static native JavaScriptObject initEscapeTable() /*-{
                                                             var out = [
                                                             "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005",
                                                             "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\u000B",
                                                             "\\f", "\\r", "\\u000E", "\\u000F", "\\u0010", "\\u0011",
                                                             "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017",
                                                             "\\u0018", "\\u0019", "\\u001A", "\\u001B", "\\u001C", "\\u001D",
                                                             "\\u001E", "\\u001F"];
                                                             out[34] = '\\"';
                                                             out[92] = '\\\\';
                                                             out[0xad] = '\\u00ad'; // Soft hyphen
                                                             out[0x600] = '\\u0600'; // Arabic number sign
                                                             out[0x601] = '\\u0601'; // Arabic sign sanah
                                                             out[0x602] = '\\u0602'; // Arabic footnote marker
                                                             out[0x603] = '\\u0603'; // Arabic sign safha
                                                             out[0x6dd] = '\\u06dd'; // Arabic and of ayah
                                                             out[0x70f] = '\\u070f'; // Syriac abbreviation mark
                                                             out[0x17b4] = '\\u17b4'; // Khmer vowel inherent aq
                                                             out[0x17b5] = '\\u17b5'; // Khmer vowel inherent aa
                                                             out[0x200c] = '\\u200c'; // Zero width non-joiner
                                                             out[0x200d] = '\\u200d'; // Zero width joiner
                                                             out[0x200e] = '\\u200e'; // Left-to-right mark
                                                             out[0x200f] = '\\u200f'; // Right-to-left mark
                                                             out[0x2028] = '\\u2028'; // Line separator
                                                             out[0x2029] = '\\u2029'; // Paragraph separator
                                                             out[0x202a] = '\\u202a'; // Left-to-right embedding
                                                             out[0x202b] = '\\u202b'; // Right-to-left embedding
                                                             out[0x202c] = '\\u202c'; // Pop directional formatting
                                                             out[0x202d] = '\\u202d'; // Left-to-right override
                                                             out[0x202e] = '\\u202e'; // Right-to-left override
                                                             out[0x2060] = '\\u2060'; // Word joiner
                                                             out[0x2061] = '\\u2061'; // Function application
                                                             out[0x2062] = '\\u2062'; // Invisible times
                                                             out[0x2063] = '\\u2063'; // Invisible separator
                                                             out[0x206a] = '\\u206a'; // Inhibit symmetric swapping
                                                             out[0x206b] = '\\u206b'; // Activate symmetric swapping
                                                             out[0x206c] = '\\u206c'; // Inherent Arabic form shaping
                                                             out[0x206d] = '\\u206d'; // Activate Arabic form shaping
                                                             out[0x206e] = '\\u206e'; // National digit shapes
                                                             out[0x206f] = '\\u206f'; // Nominal digit shapes
                                                             out[0xfeff] = '\\ufeff'; // Zero width no-break space
                                                             out[0xfff9] = '\\ufff9'; // Intralinear annotation anchor
                                                             out[0xfffa] = '\\ufffa'; // Intralinear annotation separator
                                                             out[0xfffb] = '\\ufffb'; // Intralinear annotation terminator
                                                             return out;
                                                             }-*/;

    private JsonUtils() {
    }
}