jsondecoder.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 427 行

JAVA
427
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * *   Free Software Foundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Nam Nguyen */package com.caucho.bayeux;import java.util.ArrayList;import java.util.HashMap;import com.caucho.util.L10N;class JsonDecoder {  private static final L10N L = new L10N(JsonDecoder.class);  private String _string;  private int _len;  private int _offset;  private JsonDecoder(String string)  {    _string = string;    _len = _string.length();    _offset = 0;  }  public static JsonObject decode(String string)    throws JsonDecodingException  {    return new JsonDecoder(string).decode();  }    private JsonObject decode()    throws JsonDecodingException  {    JsonObject object = decodeObject();    // Should now be at end of string or have only white spaces left.    if (skipWhitespace() >= 0)      error("expected no more input");    return object;  }  /**   * Entry point to decode a JSON value.   *   * @return decoded PHP value    */  private JsonObject decodeObject()    throws JsonDecodingException  {    for (int ch = skipWhitespace(); ch >= 0; ch = read()) {      switch (ch) {        case '"':          return decodeString();        case 't':          if (read() == 'r' &&              read() == 'u' &&              read() == 'e')            return JsonBoolean.TRUE;          else            error("expected 'true'");        case 'f':          if (read() == 'a' &&              read() == 'l' &&              read() == 's' &&              read() == 'e')            return JsonBoolean.FALSE;          else            error("expected 'false'");        case 'n':          if (read() == 'u' &&              read() == 'l' &&              read() == 'l')            return JsonNull.NULL;          else            error("expected 'null'");        case '[':          return decodeArray();        case '{':          return decodeMap();        default:          if (ch == '-' || ('0' <= ch && ch <= '9')) {            unread();            return decodeNumber();          }          else            error();      }    }    error();    return null;  }  /**   * Checks to see if there is a valid number per JSON Internet Draft.   */  private JsonNumber decodeNumber()    throws JsonDecodingException  {    StringBuilder sb = new StringBuilder();    int ch = read();    // (-)?    if (ch == '-') {      sb.append((char)ch);      ch = read();    }    // (0) | ([1-9] [0-9]+)    if (ch >= 0) {      if (ch == '0') {        sb.append((char)ch);        ch = read();      }      else if ('1' <= ch && ch <= '9') {        sb.append((char)ch);        ch = read();        while ('0' <= ch && ch <= '9') {          sb.append((char)ch);          ch = read();        }      }      else        error("expected 1-9");    }    int integerEnd = sb.length();    // ((decimalPoint) [0-9]+)?    if (ch == '.') {      sb.append((char)ch);      ch = read();      while ('0' <= ch && ch <= '9') {        sb.append((char)ch);        ch = read();      }    }    // ((e | E) (+ | -)? [0-9]+)    if (ch == 'e' || ch == 'E') {      sb.append((char)ch);      ch = read();      if (ch == '+' || ch == '-') {        sb.append((char)ch);        ch = read();      }      if ('0' <= ch && ch <= '9') {        sb.append((char)ch);        ch = read();        while ('0' <= ch && ch <= '9') {          sb.append((char)ch);          ch = read();        }      }      else        error("expected 0-9 exponent");    }    unread();    if (integerEnd != sb.length())      return JsonDouble.valueOf(Double.parseDouble(sb.toString()));    else      return JsonLong.valueOf(Long.parseLong(sb.toString()));  }  /**   * Returns an array list.   */  private JsonArray decodeArray()    throws JsonDecodingException  {    JsonArray array = new JsonArray();    while (true) {      int ch = skipWhitespace();      if (ch == ']')        break;      unread();      array.add(decodeObject());      ch = skipWhitespace();      if (ch == ',') {      }      else if (ch == ']')        break;      else        error("expected either ',' or ']'");    }    return array;  }  /**   * Returns a map version of a JSON object.   */  private JsonMap decodeMap()    throws JsonDecodingException  {    JsonMap map = new JsonMap();    while (true) {      int ch = skipWhitespace();      if (ch == '}')        break;      unread();      JsonObject name = decodeObject();      if (name == null)        error("field names must not be null");      if (! (name instanceof JsonString))        error("field names must be strings");      ch = skipWhitespace();      if (ch != ':')        error("expected ':'");      map.put(name.toString(), decodeObject());      ch = skipWhitespace();      if (ch == ',') {      }      else if (ch == '}')        break;      else        error("expected either ',' or '}'");    }    return map;  }  /**   * Returns a string.   */  private JsonString decodeString()    throws JsonDecodingException  {    StringBuilder sb = new StringBuilder();    for (int ch = read(); ch >= 0; ch = read()) {      switch (ch) {        // Escaped Characters        case '\\':          ch = read();          if (ch < 0)            error("invalid escape character");          switch (ch) {            case '"':              sb.append('"');              break;            case '\\':              sb.append('\\');              break;            case '/':              sb.append('/');              break;            case 'b':              sb.append('\b');              break;            case 'f':              sb.append('\f');              break;            case 'n':              sb.append('\n');              break;            case 'r':              sb.append('\r');              break;            case 't':              sb.append('\t');              break;            case 'u':            case 'U':              int hex = 0;              for (int i = 0; i < 4; i++) {                hex = hex << 4;                ch = read();                if ('0' <= ch && ch <= '9')                  hex += ch - '0';                else if (ch >= 'a' && ch <= 'f')                  hex += ch - 'a' + 10;                else if (ch >= 'A' && ch <= 'F')                  hex += ch - 'A' + 10;                else                  error("invalid escaped hex character");              }              sb.append((char)hex);          }          break;        case '"':          return JsonString.valueOf(sb.toString());        default:          sb.append((char)ch);      }    }    error("error decoding string");    return null;  }  private void error()    throws JsonDecodingException  {    error(null);  }  private void error(String message)    throws JsonDecodingException  {    int start;    int end;    if (_offset < _len) {      start = _offset - 1;      end = _offset;    }    else {      start = _len - 1;      end = _len;    }    String token = _string.substring(start, end).toString();    if (message != null)      throw new JsonDecodingException(L.l("error parsing '{0}': {1}",                                           token, message));    else      throw new JsonDecodingException(L.l("error parsing '{0}'", token));  }  private void unread()  {    if (_offset > 0)      _offset--;  }  private int peek(int index)  {    if (0 <= index && index < _len)      return _string.charAt(index);    else      return -1;  }  private int read()  {    if (_offset < _len)      return _string.charAt(_offset++);    else      return -1;  }  private int skipWhitespace()  {    int ch = read();    for (; ch >= 0; ch = read()) {      if (ch != ' ' &&          ch != '\n' &&          ch != '\r' &&          ch != '\t')        break;    }    return ch;  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?