github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgRpc/kmgRpcJava/java/src/com/google/gson/internal/bind/JsonTreeReader.java (about)

     1  /*
     2   * Copyright (C) 2011 Google Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *      http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package com.google.gson.internal.bind;
    18  
    19  import com.google.gson.JsonArray;
    20  import com.google.gson.JsonElement;
    21  import com.google.gson.JsonNull;
    22  import com.google.gson.JsonObject;
    23  import com.google.gson.JsonPrimitive;
    24  import com.google.gson.stream.JsonReader;
    25  import com.google.gson.stream.JsonToken;
    26  import java.io.IOException;
    27  import java.io.Reader;
    28  import java.util.ArrayList;
    29  import java.util.Iterator;
    30  import java.util.List;
    31  import java.util.Map;
    32  
    33  /**
    34   * This reader walks the elements of a JsonElement as if it was coming from a
    35   * character stream.
    36   *
    37   * @author Jesse Wilson
    38   */
    39  public final class JsonTreeReader extends JsonReader {
    40    private static final Reader UNREADABLE_READER = new Reader() {
    41      @Override public int read(char[] buffer, int offset, int count) throws IOException {
    42        throw new AssertionError();
    43      }
    44      @Override public void close() throws IOException {
    45        throw new AssertionError();
    46      }
    47    };
    48    private static final Object SENTINEL_CLOSED = new Object();
    49  
    50    private final List<Object> stack = new ArrayList<Object>();
    51  
    52    public JsonTreeReader(JsonElement element) {
    53      super(UNREADABLE_READER);
    54      stack.add(element);
    55    }
    56  
    57    @Override public void beginArray() throws IOException {
    58      expect(JsonToken.BEGIN_ARRAY);
    59      JsonArray array = (JsonArray) peekStack();
    60      stack.add(array.iterator());
    61    }
    62  
    63    @Override public void endArray() throws IOException {
    64      expect(JsonToken.END_ARRAY);
    65      popStack(); // empty iterator
    66      popStack(); // array
    67    }
    68  
    69    @Override public void beginObject() throws IOException {
    70      expect(JsonToken.BEGIN_OBJECT);
    71      JsonObject object = (JsonObject) peekStack();
    72      stack.add(object.entrySet().iterator());
    73    }
    74  
    75    @Override public void endObject() throws IOException {
    76      expect(JsonToken.END_OBJECT);
    77      popStack(); // empty iterator
    78      popStack(); // object
    79    }
    80  
    81    @Override public boolean hasNext() throws IOException {
    82      JsonToken token = peek();
    83      return token != JsonToken.END_OBJECT && token != JsonToken.END_ARRAY;
    84    }
    85  
    86    @Override public JsonToken peek() throws IOException {
    87      if (stack.isEmpty()) {
    88        return JsonToken.END_DOCUMENT;
    89      }
    90  
    91      Object o = peekStack();
    92      if (o instanceof Iterator) {
    93        boolean isObject = stack.get(stack.size() - 2) instanceof JsonObject;
    94        Iterator<?> iterator = (Iterator<?>) o;
    95        if (iterator.hasNext()) {
    96          if (isObject) {
    97            return JsonToken.NAME;
    98          } else {
    99            stack.add(iterator.next());
   100            return peek();
   101          }
   102        } else {
   103          return isObject ? JsonToken.END_OBJECT : JsonToken.END_ARRAY;
   104        }
   105      } else if (o instanceof JsonObject) {
   106        return JsonToken.BEGIN_OBJECT;
   107      } else if (o instanceof JsonArray) {
   108        return JsonToken.BEGIN_ARRAY;
   109      } else if (o instanceof JsonPrimitive) {
   110        JsonPrimitive primitive = (JsonPrimitive) o;
   111        if (primitive.isString()) {
   112          return JsonToken.STRING;
   113        } else if (primitive.isBoolean()) {
   114          return JsonToken.BOOLEAN;
   115        } else if (primitive.isNumber()) {
   116          return JsonToken.NUMBER;
   117        } else {
   118          throw new AssertionError();
   119        }
   120      } else if (o instanceof JsonNull) {
   121        return JsonToken.NULL;
   122      } else if (o == SENTINEL_CLOSED) {
   123        throw new IllegalStateException("JsonReader is closed");
   124      } else {
   125        throw new AssertionError();
   126      }
   127    }
   128  
   129    private Object peekStack() {
   130      return stack.get(stack.size() - 1);
   131    }
   132  
   133    private Object popStack() {
   134      return stack.remove(stack.size() - 1);
   135    }
   136  
   137    private void expect(JsonToken expected) throws IOException {
   138      if (peek() != expected) {
   139        throw new IllegalStateException("Expected " + expected + " but was " + peek());
   140      }
   141    }
   142  
   143    @Override public String nextName() throws IOException {
   144      expect(JsonToken.NAME);
   145      Iterator<?> i = (Iterator<?>) peekStack();
   146      Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
   147      stack.add(entry.getValue());
   148      return (String) entry.getKey();
   149    }
   150  
   151    @Override public String nextString() throws IOException {
   152      JsonToken token = peek();
   153      if (token != JsonToken.STRING && token != JsonToken.NUMBER) {
   154        throw new IllegalStateException("Expected " + JsonToken.STRING + " but was " + token);
   155      }
   156      return ((JsonPrimitive) popStack()).getAsString();
   157    }
   158  
   159    @Override public boolean nextBoolean() throws IOException {
   160      expect(JsonToken.BOOLEAN);
   161      return ((JsonPrimitive) popStack()).getAsBoolean();
   162    }
   163  
   164    @Override public void nextNull() throws IOException {
   165      expect(JsonToken.NULL);
   166      popStack();
   167    }
   168  
   169    @Override public double nextDouble() throws IOException {
   170      JsonToken token = peek();
   171      if (token != JsonToken.NUMBER && token != JsonToken.STRING) {
   172        throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token);
   173      }
   174      double result = ((JsonPrimitive) peekStack()).getAsDouble();
   175      if (!isLenient() && (Double.isNaN(result) || Double.isInfinite(result))) {
   176        throw new NumberFormatException("JSON forbids NaN and infinities: " + result);
   177      }
   178      popStack();
   179      return result;
   180    }
   181  
   182    @Override public long nextLong() throws IOException {
   183      JsonToken token = peek();
   184      if (token != JsonToken.NUMBER && token != JsonToken.STRING) {
   185        throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token);
   186      }
   187      long result = ((JsonPrimitive) peekStack()).getAsLong();
   188      popStack();
   189      return result;
   190    }
   191  
   192    @Override public int nextInt() throws IOException {
   193      JsonToken token = peek();
   194      if (token != JsonToken.NUMBER && token != JsonToken.STRING) {
   195        throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token);
   196      }
   197      int result = ((JsonPrimitive) peekStack()).getAsInt();
   198      popStack();
   199      return result;
   200    }
   201  
   202    @Override public void close() throws IOException {
   203      stack.clear();
   204      stack.add(SENTINEL_CLOSED);
   205    }
   206  
   207    @Override public void skipValue() throws IOException {
   208      if (peek() == JsonToken.NAME) {
   209        nextName();
   210      } else {
   211        popStack();
   212      }
   213    }
   214  
   215    @Override public String toString() {
   216      return getClass().getSimpleName();
   217    }
   218  
   219    public void promoteNameToValue() throws IOException {
   220      expect(JsonToken.NAME);
   221      Iterator<?> i = (Iterator<?>) peekStack();
   222      Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
   223      stack.add(entry.getValue());
   224      stack.add(new JsonPrimitive((String)entry.getKey()));
   225    }
   226  }