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

com.rabbitmq.tools.json.JSONReader Maven / Gradle / Ivy

Go to download

The RabbitMQ Java client library allows Java applications to interface with RabbitMQ.

The newest version!
// Copyright (c) 2007-2023 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
//
// This software, the RabbitMQ Java client library, is triple-licensed under the
// Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2
// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see
// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2.  For the ASL,
// please see LICENSE-APACHE2.
//
// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
// either express or implied. See the LICENSE file for specific language governing
// rights and limitations of this software.
//
// If you have any questions regarding licensing, please contact us at
// [email protected].

/*
   Copyright (c) 2006-2007 Frank Carver
   Copyright (c) 2007-2023 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.

   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

       https://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.
*/
/*
 * Based on org.stringtree.json.JSONReader, licensed under APL and
 * LGPL. We've chosen APL (see above). The original code was written
 * by Frank Carver. Tony Garnock-Jones has made many changes to it
 * since then.
 */
package com.rabbitmq.tools.json;

import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Will be removed in 6.0
 *
 * @deprecated Use a third-party JSON library, e.g. Jackson or Gson
 */
public class JSONReader {

    private static final Object OBJECT_END = new Object();
    private static final Object ARRAY_END = new Object();
    private static final Object COLON = new Object();
    private static final Object COMMA = new Object();

    private static final Map escapes = new HashMap();
    static {
        escapes.put(Character.valueOf('"'), Character.valueOf('"'));
        escapes.put(Character.valueOf('\\'), Character.valueOf('\\'));
        escapes.put(Character.valueOf('/'), Character.valueOf('/'));
        escapes.put(Character.valueOf('b'), Character.valueOf('\b'));
        escapes.put(Character.valueOf('f'), Character.valueOf('\f'));
        escapes.put(Character.valueOf('n'), Character.valueOf('\n'));
        escapes.put(Character.valueOf('r'), Character.valueOf('\r'));
        escapes.put(Character.valueOf('t'), Character.valueOf('\t'));
    }

    private CharacterIterator it;
    private char c;
    private Object token;
    private final StringBuilder buf = new StringBuilder();

    private char next() {
        c = it.next();
        return c;
    }

    private void skipWhiteSpace() {
        boolean cont;

        do {
            cont = true;
            if (Character.isWhitespace(c)) {
                next();
            }
            else if (c == '/' && next() == '/') {
                while (c != '\n') {
                    next();
                }
            }
            else {
                cont = false;
            }
        } while (cont);
    }

    public Object read(String string) {
        it = new StringCharacterIterator(string);
        c = it.first();
        return read();
    }

    private Object read() {
        Object ret = null;
        skipWhiteSpace();

        if (c == '"' || c == '\'') {
            char sep = c;
            next();
            ret = string(sep);
        } else if (c == '[') {
            next();
            ret = array();
        } else if (c == ']') {
            ret = ARRAY_END;
            next();
        } else if (c == ',') {
            ret = COMMA;
            next();
        } else if (c == '{') {
            next();
            ret = object();
        } else if (c == '}') {
            ret = OBJECT_END;
            next();
        } else if (c == ':') {
            ret = COLON;
            next();
        } else if (c == 't' && next() == 'r' && next() == 'u' && next() == 'e') {
            ret = Boolean.TRUE;
            next();
        } else if (c == 'f' && next() == 'a' && next() == 'l' && next() == 's' && next() == 'e') {
            ret = Boolean.FALSE;
            next();
        } else if (c == 'n' && next() == 'u' && next() == 'l' && next() == 'l') {
            next();
        } else if (Character.isDigit(c) || c == '-') {
            ret = number();
        }
        else {
            throw new IllegalStateException("Found invalid token while parsing JSON (around character "+(it.getIndex()-it.getBeginIndex())+"): " + ret);
        }

        token = ret;
        return ret;
    }

    private Object object() {
        Map ret = new HashMap();
        String key = (String) read(); // JSON keys must be strings
        while (token != OBJECT_END) {
            read(); // should be a colon
            if (token != OBJECT_END) {
                ret.put(key, read());
                if (read() == COMMA) {
                    key = (String) read();
                }
            }
        }

        return ret;
    }

    private Object array() {
        List ret = new ArrayList();
        Object value = read();
        while (token != ARRAY_END) {
            ret.add(value);
            if (read() == COMMA) {
                value = read();
            }
        }
        return ret;
    }

    private Object number() {
        buf.setLength(0);
        if (c == '-') {
            add();
        }
        addDigits();
        if (c == '.') {
            add();
            addDigits();
        }
        if (c == 'e' || c == 'E') {
            add();
            if (c == '+' || c == '-') {
                add();
            }
            addDigits();
        }

        String result = buf.toString();
        try {
            return Integer.valueOf(result);
        } catch (NumberFormatException nfe) {
            return Double.valueOf(result);
        }
    }

    /**
     * Read a string with a specific delimiter (either ' or ")
     */
    private Object string(char sep) {
        buf.setLength(0);
        while (c != sep) {
            if (c == '\\') {
                next();
                if (c == 'u') {
                    add(unicode());
                } else {
                    Object value = escapes.get(Character.valueOf(c));
                    if (value != null) {
                        add(((Character) value).charValue());
                    }
                    // if escaping is invalid, if we're going to ignore the error,
                    // it makes more sense to put in the literal character instead
                    // of just skipping it, so we do that
                    else {
                        add();
                    }
                }
            } else {
                add();
            }
        }
        next();

        return buf.toString();
    }

    private void add(char cc) {
        buf.append(cc);
        next();
    }

    private void add() {
        add(c);
    }

    private void addDigits() {
        while (Character.isDigit(c)) {
            add();
        }
    }

    private char unicode() {
        int value = 0;
        for (int i = 0; i < 4; ++i) {
            switch (next()) {
            case '0': case '1': case '2': case '3': case '4':
            case '5': case '6': case '7': case '8': case '9':
                value = (value << 4) + c - '0';
                break;
            case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
                value = (value << 4) + c - 'a' + 10;
                break;
            case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
                value = (value << 4) + c - 'A' + 10;
                break;
            }
        }
        return (char) value;
    }
}