5f9f0395d27a967058ac65bb29b58bdff2117777
[unical.git] / gson / com / google / gson / internal / bind / JsonTreeWriter.java
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.JsonWriter;
25 import java.io.IOException;
26 import java.io.Writer;
27 import java.util.ArrayList;
28 import java.util.List;
29
30 /**
31 * This writer creates a JsonElement.
32 */
33 public final class JsonTreeWriter extends JsonWriter {
34 private static final Writer UNWRITABLE_WRITER = new Writer() {
35 @Override public void write(char[] buffer, int offset, int counter) {
36 throw new AssertionError();
37 }
38 @Override public void flush() throws IOException {
39 throw new AssertionError();
40 }
41 @Override public void close() throws IOException {
42 throw new AssertionError();
43 }
44 };
45 /** Added to the top of the stack when this writer is closed to cause following ops to fail. */
46 private static final JsonPrimitive SENTINEL_CLOSED = new JsonPrimitive("closed");
47
48 /** The JsonElements and JsonArrays under modification, outermost to innermost. */
49 private final List<JsonElement> stack = new ArrayList<JsonElement>();
50
51 /** The name for the next JSON object value. If non-null, the top of the stack is a JsonObject. */
52 private String pendingName;
53
54 /** the JSON element constructed by this writer. */
55 private JsonElement product = JsonNull.INSTANCE; // TODO: is this really what we want?;
56
57 public JsonTreeWriter() {
58 super(UNWRITABLE_WRITER);
59 }
60
61 /**
62 * Returns the top level object produced by this writer.
63 */
64 public JsonElement get() {
65 if (!stack.isEmpty()) {
66 throw new IllegalStateException("Expected one JSON element but was " + stack);
67 }
68 return product;
69 }
70
71 private JsonElement peek() {
72 return stack.get(stack.size() - 1);
73 }
74
75 private void put(JsonElement value) {
76 if (pendingName != null) {
77 if (!value.isJsonNull() || getSerializeNulls()) {
78 JsonObject object = (JsonObject) peek();
79 object.add(pendingName, value);
80 }
81 pendingName = null;
82 } else if (stack.isEmpty()) {
83 product = value;
84 } else {
85 JsonElement element = peek();
86 if (element instanceof JsonArray) {
87 ((JsonArray) element).add(value);
88 } else {
89 throw new IllegalStateException();
90 }
91 }
92 }
93
94 @Override public JsonWriter beginArray() throws IOException {
95 JsonArray array = new JsonArray();
96 put(array);
97 stack.add(array);
98 return this;
99 }
100
101 @Override public JsonWriter endArray() throws IOException {
102 if (stack.isEmpty() || pendingName != null) {
103 throw new IllegalStateException();
104 }
105 JsonElement element = peek();
106 if (element instanceof JsonArray) {
107 stack.remove(stack.size() - 1);
108 return this;
109 }
110 throw new IllegalStateException();
111 }
112
113 @Override public JsonWriter beginObject() throws IOException {
114 JsonObject object = new JsonObject();
115 put(object);
116 stack.add(object);
117 return this;
118 }
119
120 @Override public JsonWriter endObject() throws IOException {
121 if (stack.isEmpty() || pendingName != null) {
122 throw new IllegalStateException();
123 }
124 JsonElement element = peek();
125 if (element instanceof JsonObject) {
126 stack.remove(stack.size() - 1);
127 return this;
128 }
129 throw new IllegalStateException();
130 }
131
132 @Override public JsonWriter name(String name) throws IOException {
133 if (stack.isEmpty() || pendingName != null) {
134 throw new IllegalStateException();
135 }
136 JsonElement element = peek();
137 if (element instanceof JsonObject) {
138 pendingName = name;
139 return this;
140 }
141 throw new IllegalStateException();
142 }
143
144 @Override public JsonWriter value(String value) throws IOException {
145 if (value == null) {
146 return nullValue();
147 }
148 put(new JsonPrimitive(value));
149 return this;
150 }
151
152 @Override public JsonWriter nullValue() throws IOException {
153 put(JsonNull.INSTANCE);
154 return this;
155 }
156
157 @Override public JsonWriter value(boolean value) throws IOException {
158 put(new JsonPrimitive(value));
159 return this;
160 }
161
162 @Override public JsonWriter value(double value) throws IOException {
163 if (!isLenient() && (Double.isNaN(value) || Double.isInfinite(value))) {
164 throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value);
165 }
166 put(new JsonPrimitive(value));
167 return this;
168 }
169
170 @Override public JsonWriter value(long value) throws IOException {
171 put(new JsonPrimitive(value));
172 return this;
173 }
174
175 @Override public JsonWriter value(Number value) throws IOException {
176 if (value == null) {
177 return nullValue();
178 }
179
180 if (!isLenient()) {
181 double d = value.doubleValue();
182 if (Double.isNaN(d) || Double.isInfinite(d)) {
183 throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value);
184 }
185 }
186
187 put(new JsonPrimitive(value));
188 return this;
189 }
190
191 @Override public void flush() throws IOException {
192 }
193
194 @Override public void close() throws IOException {
195 if (!stack.isEmpty()) {
196 throw new IOException("Incomplete document");
197 }
198 stack.add(SENTINEL_CLOSED);
199 }
200 }
This page took 0.026091 seconds and 3 git commands to generate.