1
16 package com.squareup.moshi;
17
18 import java.io.IOException;
19 import java.lang.annotation.Annotation;
20 import java.lang.reflect.Type;
21 import java.math.BigDecimal;
22 import java.util.Set;
23 import javax.annotation.CheckReturnValue;
24 import javax.annotation.Nullable;
25 import okio.Buffer;
26 import okio.BufferedSink;
27 import okio.BufferedSource;
28
29
32 public abstract class JsonAdapter<T> {
33 @CheckReturnValue public abstract @Nullable T fromJson(JsonReader reader) throws IOException;
34
35 @CheckReturnValue public final @Nullable T fromJson(BufferedSource source) throws IOException {
36 return fromJson(JsonReader.of(source));
37 }
38
39 @CheckReturnValue public final @Nullable T fromJson(String string) throws IOException {
40 JsonReader reader = JsonReader.of(new Buffer().writeUtf8(string));
41 T result = fromJson(reader);
42 if (!isLenient() && reader.peek() != JsonReader.Token.END_DOCUMENT) {
43 throw new JsonDataException("JSON document was not fully consumed.");
44 }
45 return result;
46 }
47
48 public abstract void toJson(JsonWriter writer, @Nullable T value) throws IOException;
49
50 public final void toJson(BufferedSink sink, @Nullable T value) throws IOException {
51 JsonWriter writer = JsonWriter.of(sink);
52 toJson(writer, value);
53 }
54
55 @CheckReturnValue public final String toJson(@Nullable T value) {
56 Buffer buffer = new Buffer();
57 try {
58 toJson(buffer, value);
59 } catch (IOException e) {
60 throw new AssertionError(e);
61 }
62 return buffer.readUtf8();
63 }
64
65
75 @CheckReturnValue public final @Nullable Object toJsonValue(@Nullable T value) {
76 JsonValueWriter writer = new JsonValueWriter();
77 try {
78 toJson(writer, value);
79 return writer.root();
80 } catch (IOException e) {
81 throw new AssertionError(e);
82 }
83 }
84
85
89 @CheckReturnValue public final @Nullable T fromJsonValue(@Nullable Object value) {
90 JsonValueReader reader = new JsonValueReader(value);
91 try {
92 return fromJson(reader);
93 } catch (IOException e) {
94 throw new AssertionError(e);
95 }
96 }
97
98
102 @CheckReturnValue public final JsonAdapter<T> serializeNulls() {
103 final JsonAdapter<T> delegate = this;
104 return new JsonAdapter<T>() {
105 @Override public @Nullable T fromJson(JsonReader reader) throws IOException {
106 return delegate.fromJson(reader);
107 }
108 @Override public void toJson(JsonWriter writer, @Nullable T value) throws IOException {
109 boolean serializeNulls = writer.getSerializeNulls();
110 writer.setSerializeNulls(true);
111 try {
112 delegate.toJson(writer, value);
113 } finally {
114 writer.setSerializeNulls(serializeNulls);
115 }
116 }
117 @Override boolean isLenient() {
118 return delegate.isLenient();
119 }
120 @Override public String toString() {
121 return delegate + ".serializeNulls()";
122 }
123 };
124 }
125
126
130 @CheckReturnValue public final JsonAdapter<T> nullSafe() {
131 final JsonAdapter<T> delegate = this;
132 return new JsonAdapter<T>() {
133 @Override public @Nullable T fromJson(JsonReader reader) throws IOException {
134 if (reader.peek() == JsonReader.Token.NULL) {
135 return reader.nextNull();
136 } else {
137 return delegate.fromJson(reader);
138 }
139 }
140 @Override public void toJson(JsonWriter writer, @Nullable T value) throws IOException {
141 if (value == null) {
142 writer.nullValue();
143 } else {
144 delegate.toJson(writer, value);
145 }
146 }
147 @Override boolean isLenient() {
148 return delegate.isLenient();
149 }
150 @Override public String toString() {
151 return delegate + ".nullSafe()";
152 }
153 };
154 }
155
156
163 @CheckReturnValue public final JsonAdapter<T> nonNull() {
164 final JsonAdapter<T> delegate = this;
165 return new JsonAdapter<T>() {
166 @Override public @Nullable T fromJson(JsonReader reader) throws IOException {
167 if (reader.peek() == JsonReader.Token.NULL) {
168 throw new JsonDataException("Unexpected null at " + reader.getPath());
169 } else {
170 return delegate.fromJson(reader);
171 }
172 }
173 @Override public void toJson(JsonWriter writer, @Nullable T value) throws IOException {
174 if (value == null) {
175 throw new JsonDataException("Unexpected null at " + writer.getPath());
176 } else {
177 delegate.toJson(writer, value);
178 }
179 }
180 @Override boolean isLenient() {
181 return delegate.isLenient();
182 }
183 @Override public String toString() {
184 return delegate + ".nonNull()";
185 }
186 };
187 }
188
189
190 @CheckReturnValue public final JsonAdapter<T> lenient() {
191 final JsonAdapter<T> delegate = this;
192 return new JsonAdapter<T>() {
193 @Override public @Nullable T fromJson(JsonReader reader) throws IOException {
194 boolean lenient = reader.isLenient();
195 reader.setLenient(true);
196 try {
197 return delegate.fromJson(reader);
198 } finally {
199 reader.setLenient(lenient);
200 }
201 }
202 @Override public void toJson(JsonWriter writer, @Nullable T value) throws IOException {
203 boolean lenient = writer.isLenient();
204 writer.setLenient(true);
205 try {
206 delegate.toJson(writer, value);
207 } finally {
208 writer.setLenient(lenient);
209 }
210 }
211 @Override boolean isLenient() {
212 return true;
213 }
214 @Override public String toString() {
215 return delegate + ".lenient()";
216 }
217 };
218 }
219
220
226 @CheckReturnValue public final JsonAdapter<T> failOnUnknown() {
227 final JsonAdapter<T> delegate = this;
228 return new JsonAdapter<T>() {
229 @Override public @Nullable T fromJson(JsonReader reader) throws IOException {
230 boolean skipForbidden = reader.failOnUnknown();
231 reader.setFailOnUnknown(true);
232 try {
233 return delegate.fromJson(reader);
234 } finally {
235 reader.setFailOnUnknown(skipForbidden);
236 }
237 }
238 @Override public void toJson(JsonWriter writer, @Nullable T value) throws IOException {
239 delegate.toJson(writer, value);
240 }
241 @Override boolean isLenient() {
242 return delegate.isLenient();
243 }
244 @Override public String toString() {
245 return delegate + ".failOnUnknown()";
246 }
247 };
248 }
249
250
258 @CheckReturnValue public JsonAdapter<T> indent(final String indent) {
259 if (indent == null) {
260 throw new NullPointerException("indent == null");
261 }
262 final JsonAdapter<T> delegate = this;
263 return new JsonAdapter<T>() {
264 @Override public @Nullable T fromJson(JsonReader reader) throws IOException {
265 return delegate.fromJson(reader);
266 }
267 @Override public void toJson(JsonWriter writer, @Nullable T value) throws IOException {
268 String originalIndent = writer.getIndent();
269 writer.setIndent(indent);
270 try {
271 delegate.toJson(writer, value);
272 } finally {
273 writer.setIndent(originalIndent);
274 }
275 }
276 @Override boolean isLenient() {
277 return delegate.isLenient();
278 }
279 @Override public String toString() {
280 return delegate + ".indent(\"" + indent + "\")";
281 }
282 };
283 }
284
285 boolean isLenient() {
286 return false;
287 }
288
289 public interface Factory {
290
298 @CheckReturnValue
299 @Nullable JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi);
300 }
301 }
302