newCollection() {
65 | return new LinkedHashSet<>();
66 | }
67 | };
68 | }
69 |
70 | abstract C newCollection();
71 |
72 | @Override public C fromJson(JsonReader reader) throws IOException {
73 | C result = newCollection();
74 | reader.beginArray();
75 | while (reader.hasNext()) {
76 | result.add(elementAdapter.fromJson(reader));
77 | }
78 | reader.endArray();
79 | return result;
80 | }
81 |
82 | @Override public void toJson(JsonWriter writer, C value) throws IOException {
83 | writer.beginArray();
84 | for (T element : value) {
85 | elementAdapter.toJson(writer, element);
86 | }
87 | writer.endArray();
88 | }
89 |
90 | @Override public String toString() {
91 | return elementAdapter + ".collection()";
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/moshi/src/main/java/com/squareup/moshi/FromJson.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, 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 | package com.squareup.moshi;
17 |
18 | import java.lang.annotation.ElementType;
19 | import java.lang.annotation.Retention;
20 | import java.lang.annotation.RetentionPolicy;
21 | import java.lang.annotation.Target;
22 |
23 | @Retention(RetentionPolicy.RUNTIME)
24 | @Target(ElementType.METHOD)
25 | public @interface FromJson {
26 | }
27 |
--------------------------------------------------------------------------------
/moshi/src/main/java/com/squareup/moshi/Json.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, 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 | package com.squareup.moshi;
17 |
18 | import java.lang.annotation.Documented;
19 | import java.lang.annotation.Retention;
20 | import java.lang.annotation.Target;
21 |
22 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
23 |
24 | /**
25 | * Customizes how a field is encoded as JSON.
26 | *
27 | * Although this annotation doesn't declare a {@link Target}, it is only honored in the following
28 | * elements:
29 | *
30 | *
31 | * Java class fields
32 | * Kotlin properties for use with {@code moshi-kotlin}. This includes both
33 | * properties declared in the constructor and properties declared as members.
34 | *
35 | *
36 | * Users of the AutoValue: Moshi
37 | * Extension may also use this annotation on abstract getters.
38 | */
39 | @Retention(RUNTIME)
40 | @Documented
41 | public @interface Json {
42 | String name();
43 | }
44 |
--------------------------------------------------------------------------------
/moshi/src/main/java/com/squareup/moshi/JsonClass.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Square, 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 | package com.squareup.moshi;
17 |
18 | import java.lang.annotation.Documented;
19 | import java.lang.annotation.Retention;
20 | import java.lang.reflect.Type;
21 |
22 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
23 |
24 | /**
25 | * Customizes how a type is encoded as JSON.
26 | */
27 | @Retention(RUNTIME)
28 | @Documented
29 | public @interface JsonClass {
30 | /**
31 | * True to trigger the annotation processor to generate an adapter for this type.
32 | *
33 | *
There are currently some restrictions on which types that can be used with generated
34 | * adapters:
35 | *
36 | *
37 | * The class must be implemented in Kotlin (unless using a custom generator, see
38 | * {@link #generator()}).
39 | *
40 | * The class may not be an abstract class, an inner class, or a local class.
41 | * All superclasses must be implemented in Kotlin.
42 | * All properties must be public, protected, or internal.
43 | * All properties must be either non-transient or have a default value.
44 | *
45 | */
46 | boolean generateAdapter();
47 |
48 | /**
49 | * An optional custom generator tag used to indicate which generator should be used. If empty,
50 | * Moshi's annotation processor will generate an adapter for the annotated type. If not empty,
51 | * Moshi's processor will skip it and defer to a custom generator. This can be used to allow
52 | * other custom code generation tools to run and still allow Moshi to read their generated
53 | * JsonAdapter outputs.
54 | *
55 | * Requirements for generated adapter class signatures:
56 | *
57 | *
58 | * The generated adapter must subclass {@link JsonAdapter} and be parameterized by this type.
59 | *
60 | *
61 | * {@link Types#generatedJsonAdapterName} should be used for the fully qualified class name in
62 | * order for Moshi to correctly resolve and load the generated JsonAdapter.
63 | *
64 | * The first parameter must be a {@link Moshi} instance.
65 | *
66 | * If generic, a second {@link Type[]} parameter should be declared to accept type arguments.
67 | *
68 | *
69 | *
70 | * Example for a class "CustomType":
{@code
71 | * class CustomTypeJsonAdapter(moshi: Moshi, types: Array) : JsonAdapter() {
72 | * // ...
73 | * }
74 | * }
75 | *
76 | * To help ensure your own generator meets requirements above, you can use Moshi’s built-in
77 | * generator to create the API signature to get started, then make your own generator match that
78 | * expected signature.
79 | */
80 | String generator() default "";
81 | }
82 |
--------------------------------------------------------------------------------
/moshi/src/main/java/com/squareup/moshi/JsonDataException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, 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 | package com.squareup.moshi;
17 |
18 | import javax.annotation.Nullable;
19 |
20 | /**
21 | * Thrown when the data in a JSON document doesn't match the data expected by the caller. For
22 | * example, suppose the application expects a boolean but the JSON document contains a string. When
23 | * the call to {@link JsonReader#nextBoolean} is made, a {@code JsonDataException} is thrown.
24 | *
25 | *
Exceptions of this type should be fixed by either changing the application code to accept
26 | * the unexpected JSON, or by changing the JSON to conform to the application's expectations.
27 | *
28 | *
This exception may also be triggered if a document's nesting exceeds 31 levels. This depth is
29 | * sufficient for all practical applications, but shallow enough to avoid uglier failures like
30 | * {@link StackOverflowError}.
31 | */
32 | public final class JsonDataException extends RuntimeException {
33 | public JsonDataException() {
34 | }
35 |
36 | public JsonDataException(@Nullable String message) {
37 | super(message);
38 | }
39 |
40 | public JsonDataException(@Nullable Throwable cause) {
41 | super(cause);
42 | }
43 |
44 | public JsonDataException(@Nullable String message, @Nullable Throwable cause) {
45 | super(message, cause);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/moshi/src/main/java/com/squareup/moshi/JsonEncodingException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Square, 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 | package com.squareup.moshi;
17 |
18 | import java.io.IOException;
19 | import javax.annotation.Nullable;
20 |
21 | /** Thrown when the data being parsed is not encoded as valid JSON. */
22 | public final class JsonEncodingException extends IOException {
23 | public JsonEncodingException(@Nullable String message) {
24 | super(message);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/moshi/src/main/java/com/squareup/moshi/JsonQualifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, 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 | package com.squareup.moshi;
17 |
18 | import java.lang.annotation.Documented;
19 | import java.lang.annotation.Retention;
20 | import java.lang.annotation.Target;
21 |
22 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
23 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
24 |
25 | /** Annotates another annotation, causing it to specialize how values are encoded and decoded. */
26 | @Target(ANNOTATION_TYPE)
27 | @Retention(RUNTIME)
28 | @Documented
29 | public @interface JsonQualifier {
30 | }
31 |
--------------------------------------------------------------------------------
/moshi/src/main/java/com/squareup/moshi/JsonScope.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 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 | package com.squareup.moshi;
17 |
18 | /** Lexical scoping elements within a JSON reader or writer. */
19 | final class JsonScope {
20 | private JsonScope() {
21 | }
22 |
23 | /** An array with no elements requires no separators or newlines before it is closed. */
24 | static final int EMPTY_ARRAY = 1;
25 |
26 | /** A array with at least one value requires a comma and newline before the next element. */
27 | static final int NONEMPTY_ARRAY = 2;
28 |
29 | /** An object with no name/value pairs requires no separators or newlines before it is closed. */
30 | static final int EMPTY_OBJECT = 3;
31 |
32 | /** An object whose most recent element is a key. The next element must be a value. */
33 | static final int DANGLING_NAME = 4;
34 |
35 | /** An object with at least one name/value pair requires a separator before the next element. */
36 | static final int NONEMPTY_OBJECT = 5;
37 |
38 | /** No object or array has been started. */
39 | static final int EMPTY_DOCUMENT = 6;
40 |
41 | /** A document with at an array or object. */
42 | static final int NONEMPTY_DOCUMENT = 7;
43 |
44 | /** A document that's been closed and cannot be accessed. */
45 | static final int CLOSED = 8;
46 |
47 | /** Sits above the actual state to indicate that a value is currently being streamed in. */
48 | static final int STREAMING_VALUE = 9;
49 |
50 | /**
51 | * Renders the path in a JSON document to a string. The {@code pathNames} and {@code pathIndices}
52 | * parameters corresponds directly to stack: At indices where the stack contains an object
53 | * (EMPTY_OBJECT, DANGLING_NAME or NONEMPTY_OBJECT), pathNames contains the name at this scope.
54 | * Where it contains an array (EMPTY_ARRAY, NONEMPTY_ARRAY) pathIndices contains the current index
55 | * in that array. Otherwise the value is undefined, and we take advantage of that by incrementing
56 | * pathIndices when doing so isn't useful.
57 | */
58 | static String getPath(int stackSize, int[] stack, String[] pathNames, int[] pathIndices) {
59 | StringBuilder result = new StringBuilder().append('$');
60 | for (int i = 0; i < stackSize; i++) {
61 | switch (stack[i]) {
62 | case EMPTY_ARRAY:
63 | case NONEMPTY_ARRAY:
64 | result.append('[').append(pathIndices[i]).append(']');
65 | break;
66 |
67 | case EMPTY_OBJECT:
68 | case DANGLING_NAME:
69 | case NONEMPTY_OBJECT:
70 | result.append('.');
71 | if (pathNames[i] != null) {
72 | result.append(pathNames[i]);
73 | }
74 | break;
75 |
76 | case NONEMPTY_DOCUMENT:
77 | case EMPTY_DOCUMENT:
78 | case CLOSED:
79 | break;
80 | }
81 | }
82 | return result.toString();
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/moshi/src/main/java/com/squareup/moshi/MapJsonAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, 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 | 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.util.Map;
22 | import java.util.Set;
23 | import javax.annotation.Nullable;
24 |
25 | /**
26 | * Converts maps with string keys to JSON objects.
27 | *
28 | * TODO: support maps with other key types and convert to/from strings.
29 | */
30 | final class MapJsonAdapter extends JsonAdapter> {
31 | public static final Factory FACTORY = new Factory() {
32 | @Override public @Nullable JsonAdapter> create(
33 | Type type, Set extends Annotation> annotations, Moshi moshi) {
34 | if (!annotations.isEmpty()) return null;
35 | Class> rawType = Types.getRawType(type);
36 | if (rawType != Map.class) return null;
37 | Type[] keyAndValue = Types.mapKeyAndValueTypes(type, rawType);
38 | return new MapJsonAdapter<>(moshi, keyAndValue[0], keyAndValue[1]).nullSafe();
39 | }
40 | };
41 |
42 | private final JsonAdapter keyAdapter;
43 | private final JsonAdapter valueAdapter;
44 |
45 | MapJsonAdapter(Moshi moshi, Type keyType, Type valueType) {
46 | this.keyAdapter = moshi.adapter(keyType);
47 | this.valueAdapter = moshi.adapter(valueType);
48 | }
49 |
50 | @Override public void toJson(JsonWriter writer, Map map) throws IOException {
51 | writer.beginObject();
52 | for (Map.Entry entry : map.entrySet()) {
53 | if (entry.getKey() == null) {
54 | throw new JsonDataException("Map key is null at " + writer.getPath());
55 | }
56 | writer.promoteValueToName();
57 | keyAdapter.toJson(writer, entry.getKey());
58 | valueAdapter.toJson(writer, entry.getValue());
59 | }
60 | writer.endObject();
61 | }
62 |
63 | @Override public Map fromJson(JsonReader reader) throws IOException {
64 | LinkedHashTreeMap result = new LinkedHashTreeMap<>();
65 | reader.beginObject();
66 | while (reader.hasNext()) {
67 | reader.promoteNameToValue();
68 | K name = keyAdapter.fromJson(reader);
69 | V value = valueAdapter.fromJson(reader);
70 | V replaced = result.put(name, value);
71 | if (replaced != null) {
72 | throw new JsonDataException("Map key '" + name + "' has multiple values at path "
73 | + reader.getPath() + ": " + replaced + " and " + value);
74 | }
75 | }
76 | reader.endObject();
77 | return result;
78 | }
79 |
80 | @Override public String toString() {
81 | return "JsonAdapter(" + keyAdapter + "=" + valueAdapter + ")";
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/moshi/src/main/java/com/squareup/moshi/ToJson.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, 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 | package com.squareup.moshi;
17 |
18 | import java.lang.annotation.ElementType;
19 | import java.lang.annotation.Retention;
20 | import java.lang.annotation.RetentionPolicy;
21 | import java.lang.annotation.Target;
22 |
23 | @Retention(RetentionPolicy.RUNTIME)
24 | @Target(ElementType.METHOD)
25 | public @interface ToJson {
26 | }
27 |
--------------------------------------------------------------------------------
/moshi/src/main/java/com/squareup/moshi/internal/NonNullJsonAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 Square, 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 | package com.squareup.moshi.internal;
17 |
18 | import com.squareup.moshi.JsonAdapter;
19 | import com.squareup.moshi.JsonDataException;
20 | import com.squareup.moshi.JsonReader;
21 | import com.squareup.moshi.JsonWriter;
22 | import java.io.IOException;
23 | import javax.annotation.Nullable;
24 |
25 | public final class NonNullJsonAdapter extends JsonAdapter {
26 |
27 | private final JsonAdapter delegate;
28 |
29 | public NonNullJsonAdapter(JsonAdapter delegate) {
30 | this.delegate = delegate;
31 | }
32 |
33 | public JsonAdapter delegate() {
34 | return delegate;
35 | }
36 |
37 | @Nullable
38 | @Override
39 | public T fromJson(JsonReader reader) throws IOException {
40 | if (reader.peek() == JsonReader.Token.NULL) {
41 | throw new JsonDataException("Unexpected null at " + reader.getPath());
42 | } else {
43 | return delegate.fromJson(reader);
44 | }
45 | }
46 |
47 | @Override
48 | public void toJson(JsonWriter writer, @Nullable T value) throws IOException {
49 | if (value == null) {
50 | throw new JsonDataException("Unexpected null at " + writer.getPath());
51 | } else {
52 | delegate.toJson(writer, value);
53 | }
54 | }
55 |
56 | @Override
57 | public String toString() {
58 | return delegate + ".nonNull()";
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/moshi/src/main/java/com/squareup/moshi/internal/NullSafeJsonAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 Square, 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 | package com.squareup.moshi.internal;
17 |
18 | import com.squareup.moshi.JsonAdapter;
19 | import com.squareup.moshi.JsonReader;
20 | import com.squareup.moshi.JsonWriter;
21 | import java.io.IOException;
22 | import javax.annotation.Nullable;
23 |
24 | public final class NullSafeJsonAdapter extends JsonAdapter {
25 |
26 | private final JsonAdapter delegate;
27 |
28 | public NullSafeJsonAdapter(JsonAdapter delegate) {
29 | this.delegate = delegate;
30 | }
31 |
32 | public JsonAdapter delegate() {
33 | return delegate;
34 | }
35 |
36 | @Override public @Nullable T fromJson(JsonReader reader) throws IOException {
37 | if (reader.peek() == JsonReader.Token.NULL) {
38 | return reader.nextNull();
39 | } else {
40 | return delegate.fromJson(reader);
41 | }
42 | }
43 |
44 | @Override public void toJson(JsonWriter writer, @Nullable T value) throws IOException {
45 | if (value == null) {
46 | writer.nullValue();
47 | } else {
48 | delegate.toJson(writer, value);
49 | }
50 | }
51 |
52 | @Override public String toString() {
53 | return delegate + ".nullSafe()";
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/moshi/src/main/java/com/squareup/moshi/package-info.java:
--------------------------------------------------------------------------------
1 | /** Moshi is modern JSON library for Android and Java. */
2 | @javax.annotation.ParametersAreNonnullByDefault
3 | package com.squareup.moshi;
4 |
--------------------------------------------------------------------------------
/moshi/src/main/resources/META-INF/proguard/moshi.pro:
--------------------------------------------------------------------------------
1 | # JSR 305 annotations are for embedding nullability information.
2 | -dontwarn javax.annotation.**
3 |
4 | -keepclasseswithmembers class * {
5 | @com.squareup.moshi.* ;
6 | }
7 |
8 | -keep @com.squareup.moshi.JsonQualifier interface *
9 |
10 | # Enum field names are used by the integrated EnumJsonAdapter.
11 | # values() is synthesized by the Kotlin compiler and is used by EnumJsonAdapter indirectly
12 | # Annotate enums with @JsonClass(generateAdapter = false) to use them with Moshi.
13 | -keepclassmembers @com.squareup.moshi.JsonClass class * extends java.lang.Enum {
14 | ;
15 | **[] values();
16 | }
17 |
18 | # The name of @JsonClass types is used to look up the generated adapter.
19 | -keepnames @com.squareup.moshi.JsonClass class *
20 |
21 | # Retain generated target class's synthetic defaults constructor and keep DefaultConstructorMarker's
22 | # name. We will look this up reflectively to invoke the type's constructor.
23 | #
24 | # We can't _just_ keep the defaults constructor because Proguard/R8's spec doesn't allow wildcard
25 | # matching preceding parameters.
26 | -keepnames class kotlin.jvm.internal.DefaultConstructorMarker
27 | -keepclassmembers @com.squareup.moshi.JsonClass @kotlin.Metadata class * {
28 | synthetic (...);
29 | }
30 |
31 | # Retain generated JsonAdapters if annotated type is retained.
32 | -if @com.squareup.moshi.JsonClass class *
33 | -keep class <1>JsonAdapter {
34 | (...);
35 | ;
36 | }
37 | -if @com.squareup.moshi.JsonClass class **$*
38 | -keep class <1>_<2>JsonAdapter {
39 | (...);
40 | ;
41 | }
42 | -if @com.squareup.moshi.JsonClass class **$*$*
43 | -keep class <1>_<2>_<3>JsonAdapter {
44 | (...);
45 | ;
46 | }
47 | -if @com.squareup.moshi.JsonClass class **$*$*$*
48 | -keep class <1>_<2>_<3>_<4>JsonAdapter {
49 | (...);
50 | ;
51 | }
52 | -if @com.squareup.moshi.JsonClass class **$*$*$*$*
53 | -keep class <1>_<2>_<3>_<4>_<5>JsonAdapter {
54 | (...);
55 | ;
56 | }
57 | -if @com.squareup.moshi.JsonClass class **$*$*$*$*$*
58 | -keep class <1>_<2>_<3>_<4>_<5>_<6>JsonAdapter {
59 | (...);
60 | ;
61 | }
62 |
--------------------------------------------------------------------------------
/moshi/src/test/java/android/util/Pair.java:
--------------------------------------------------------------------------------
1 | package android.util;
2 |
3 | public final class Pair {
4 | }
5 |
--------------------------------------------------------------------------------
/moshi/src/test/java/com/squareup/moshi/CircularAdaptersTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, 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 | package com.squareup.moshi;
17 |
18 | import com.squareup.moshi.internal.Util;
19 | import java.io.IOException;
20 | import java.lang.annotation.Annotation;
21 | import java.lang.annotation.Retention;
22 | import java.lang.reflect.Type;
23 | import java.util.Set;
24 | import org.junit.Test;
25 |
26 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
27 | import static org.assertj.core.api.Assertions.assertThat;
28 |
29 | public final class CircularAdaptersTest {
30 | static class Team {
31 | final String lead;
32 | final Project[] projects;
33 |
34 | public Team(String lead, Project... projects) {
35 | this.lead = lead;
36 | this.projects = projects;
37 | }
38 | }
39 |
40 | static class Project {
41 | final String name;
42 | final Team[] teams;
43 |
44 | Project(String name, Team... teams) {
45 | this.name = name;
46 | this.teams = teams;
47 | }
48 | }
49 |
50 | @Test public void circularAdapters() throws Exception {
51 | Moshi moshi = new Moshi.Builder().build();
52 | JsonAdapter teamAdapter = moshi.adapter(Team.class);
53 |
54 | Team team = new Team("Alice", new Project("King", new Team("Charlie",
55 | new Project("Delivery", null))));
56 | assertThat(teamAdapter.toJson(team)).isEqualTo("{\"lead\":\"Alice\",\"projects\":[{\"name\":"
57 | + "\"King\",\"teams\":[{\"lead\":\"Charlie\",\"projects\":[{\"name\":\"Delivery\"}]}]}]}");
58 |
59 | Team fromJson = teamAdapter.fromJson("{\"lead\":\"Alice\",\"projects\":[{\"name\":"
60 | + "\"King\",\"teams\":[{\"lead\":\"Charlie\",\"projects\":[{\"name\":\"Delivery\"}]}]}]}");
61 | assertThat(fromJson.lead).isEqualTo("Alice");
62 | assertThat(fromJson.projects[0].name).isEqualTo("King");
63 | assertThat(fromJson.projects[0].teams[0].lead).isEqualTo("Charlie");
64 | assertThat(fromJson.projects[0].teams[0].projects[0].name).isEqualTo("Delivery");
65 | }
66 |
67 | @Retention(RUNTIME)
68 | @JsonQualifier
69 | public @interface Left {
70 | }
71 |
72 | @Retention(RUNTIME)
73 | @JsonQualifier
74 | public @interface Right {
75 | }
76 |
77 | static class Node {
78 | final String name;
79 | final @Left Node left;
80 | final @Right Node right;
81 |
82 | Node(String name, Node left, Node right) {
83 | this.name = name;
84 | this.left = left;
85 | this.right = right;
86 | }
87 |
88 | Node plusPrefix(String prefix) {
89 | return new Node(prefix + name, left, right);
90 | }
91 |
92 | Node minusPrefix(String prefix) {
93 | if (!name.startsWith(prefix)) throw new IllegalArgumentException();
94 | return new Node(name.substring(prefix.length()), left, right);
95 | }
96 | }
97 |
98 | /**
99 | * This factory uses extensive delegation. Each node delegates to this for the left and right
100 | * subtrees, and those delegate to the built-in class adapter to do most of the serialization
101 | * work.
102 | */
103 | static class PrefixingNodeFactory implements JsonAdapter.Factory {
104 | @Override public JsonAdapter> create(
105 | Type type, Set extends Annotation> annotations, Moshi moshi) {
106 | if (type != Node.class) return null;
107 |
108 | final String prefix;
109 | if (Util.isAnnotationPresent(annotations, Left.class)) {
110 | prefix = "L ";
111 | } else if (Util.isAnnotationPresent(annotations, Right.class)) {
112 | prefix = "R ";
113 | } else {
114 | return null;
115 | }
116 |
117 | final JsonAdapter delegate = moshi.nextAdapter(this, Node.class, Util.NO_ANNOTATIONS);
118 |
119 | return new JsonAdapter() {
120 | @Override public void toJson(JsonWriter writer, Node value) throws IOException {
121 | delegate.toJson(writer, value.plusPrefix(prefix));
122 | }
123 |
124 | @Override public Node fromJson(JsonReader reader) throws IOException {
125 | Node result = delegate.fromJson(reader);
126 | return result.minusPrefix(prefix);
127 | }
128 | }.nullSafe();
129 | }
130 | }
131 |
132 | @Test public void circularAdaptersAndAnnotations() throws Exception {
133 | Moshi moshi = new Moshi.Builder()
134 | .add(new PrefixingNodeFactory())
135 | .build();
136 | JsonAdapter nodeAdapter = moshi.adapter(Node.class);
137 |
138 | Node tree = new Node("C",
139 | new Node("A", null, new Node("B", null, null)),
140 | new Node("D", null, new Node("E", null, null)));
141 | assertThat(nodeAdapter.toJson(tree)).isEqualTo("{"
142 | + "\"left\":{\"name\":\"L A\",\"right\":{\"name\":\"R B\"}},"
143 | + "\"name\":\"C\","
144 | + "\"right\":{\"name\":\"R D\",\"right\":{\"name\":\"R E\"}}"
145 | + "}");
146 |
147 | Node fromJson = nodeAdapter.fromJson("{"
148 | + "\"left\":{\"name\":\"L A\",\"right\":{\"name\":\"R B\"}},"
149 | + "\"name\":\"C\","
150 | + "\"right\":{\"name\":\"R D\",\"right\":{\"name\":\"R E\"}}"
151 | + "}");
152 | assertThat(fromJson.name).isEqualTo("C");
153 | assertThat(fromJson.left.name).isEqualTo("A");
154 | assertThat(fromJson.left.right.name).isEqualTo("B");
155 | assertThat(fromJson.right.name).isEqualTo("D");
156 | assertThat(fromJson.right.right.name).isEqualTo("E");
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/moshi/src/test/java/com/squareup/moshi/DeferredAdapterTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Square, 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 | package com.squareup.moshi;
17 |
18 | import java.lang.annotation.Annotation;
19 | import java.lang.reflect.Type;
20 | import java.util.ArrayList;
21 | import java.util.List;
22 | import java.util.Set;
23 | import java.util.concurrent.ExecutionException;
24 | import java.util.concurrent.ExecutorService;
25 | import java.util.concurrent.Executors;
26 | import java.util.concurrent.Future;
27 | import javax.annotation.Nullable;
28 | import org.junit.Test;
29 |
30 | import static org.assertj.core.api.Assertions.assertThat;
31 |
32 | public final class DeferredAdapterTest {
33 | /**
34 | * When a type's JsonAdapter is circularly-dependent, Moshi creates a 'deferred adapter' to make
35 | * the cycle work. It's important that any adapters that depend on this deferred adapter don't
36 | * leak out until it's ready.
37 | *
38 | * This test sets up a circular dependency [BlueNode -> GreenNode -> BlueNode] and then tries
39 | * to use a GreenNode JSON adapter before the BlueNode JSON adapter is built. It creates a
40 | * similar cycle [BlueNode -> RedNode -> BlueNode] so the order adapters are retrieved is
41 | * insignificant.
42 | *
43 | *
This used to trigger a crash because we'd incorrectly put the GreenNode JSON adapter in the
44 | * cache even though it depended upon an incomplete BlueNode JSON adapter.
45 | */
46 | @Test public void concurrentSafe() {
47 | final List failures = new ArrayList<>();
48 |
49 | JsonAdapter.Factory factory = new JsonAdapter.Factory() {
50 | int redAndGreenCount = 0;
51 |
52 | @Override public @Nullable JsonAdapter> create(
53 | Type type, Set extends Annotation> annotations, final Moshi moshi) {
54 | if ((type == RedNode.class || type == GreenNode.class) && redAndGreenCount++ == 1) {
55 | doInAnotherThread(new Runnable() {
56 | @Override public void run() {
57 | GreenNode greenBlue = new GreenNode(new BlueNode(null, null));
58 | assertThat(moshi.adapter(GreenNode.class).toJson(greenBlue))
59 | .isEqualTo("{\"blue\":{}}");
60 |
61 | RedNode redBlue = new RedNode(new BlueNode(null, null));
62 | assertThat(moshi.adapter(RedNode.class).toJson(redBlue))
63 | .isEqualTo("{\"blue\":{}}");
64 | }
65 | });
66 | }
67 | return null;
68 | }
69 | };
70 |
71 | Moshi moshi = new Moshi.Builder()
72 | .add(factory)
73 | .build();
74 |
75 | JsonAdapter jsonAdapter = moshi.adapter(BlueNode.class);
76 | assertThat(jsonAdapter.toJson(new BlueNode(new GreenNode(new BlueNode(null, null)), null)))
77 | .isEqualTo("{\"green\":{\"blue\":{}}}");
78 |
79 | assertThat(failures).isEmpty();
80 | }
81 |
82 | private void doInAnotherThread(Runnable runnable) {
83 | ExecutorService executor = Executors.newSingleThreadExecutor();
84 | Future> future = executor.submit(runnable);
85 | executor.shutdown();
86 | try {
87 | future.get();
88 | } catch (InterruptedException e) {
89 | throw new RuntimeException(e);
90 | } catch (ExecutionException e) {
91 | throw new RuntimeException(e.getCause());
92 | }
93 | }
94 |
95 | static class BlueNode {
96 | @Nullable GreenNode green;
97 | @Nullable RedNode red;
98 |
99 | BlueNode(@Nullable GreenNode green, @Nullable RedNode red) {
100 | this.green = green;
101 | this.red = red;
102 | }
103 | }
104 |
105 | static class RedNode {
106 | @Nullable BlueNode blue;
107 |
108 | RedNode(@Nullable BlueNode blue) {
109 | this.blue = blue;
110 | }
111 | }
112 |
113 | static class GreenNode {
114 | @Nullable BlueNode blue;
115 |
116 | GreenNode(@Nullable BlueNode blue) {
117 | this.blue = blue;
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/moshi/src/test/java/com/squareup/moshi/JsonCodecFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Square, 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 | package com.squareup.moshi;
17 |
18 | import java.io.IOException;
19 | import java.util.Arrays;
20 | import java.util.List;
21 | import okio.Buffer;
22 |
23 | abstract class JsonCodecFactory {
24 | private static final Moshi MOSHI = new Moshi.Builder().build();
25 | private static final JsonAdapter OBJECT_ADAPTER = MOSHI.adapter(Object.class);
26 |
27 | static List factories() {
28 | final JsonCodecFactory utf8 = new JsonCodecFactory() {
29 | Buffer buffer;
30 |
31 | @Override public JsonReader newReader(String json) {
32 | Buffer buffer = new Buffer().writeUtf8(json);
33 | return JsonReader.of(buffer);
34 | }
35 |
36 | @Override JsonWriter newWriter() {
37 | buffer = new Buffer();
38 | return new JsonUtf8Writer(buffer);
39 | }
40 |
41 | @Override String json() {
42 | String result = buffer.readUtf8();
43 | buffer = null;
44 | return result;
45 | }
46 |
47 | @Override boolean encodesToBytes() {
48 | return true;
49 | }
50 |
51 | @Override public String toString() {
52 | return "Utf8";
53 | }
54 | };
55 |
56 | final JsonCodecFactory value = new JsonCodecFactory() {
57 | JsonValueWriter writer;
58 |
59 | @Override public JsonReader newReader(String json) throws IOException {
60 | Moshi moshi = new Moshi.Builder().build();
61 | Object object = moshi.adapter(Object.class).lenient().fromJson(json);
62 | return new JsonValueReader(object);
63 | }
64 |
65 | // TODO(jwilson): fix precision checks and delete his method.
66 | @Override boolean implementsStrictPrecision() {
67 | return false;
68 | }
69 |
70 | @Override JsonWriter newWriter() {
71 | writer = new JsonValueWriter();
72 | return writer;
73 | }
74 |
75 | @Override String json() {
76 | // This writer writes a DOM. Use other Moshi features to serialize it as a string.
77 | try {
78 | Buffer buffer = new Buffer();
79 | JsonWriter bufferedSinkWriter = JsonWriter.of(buffer);
80 | bufferedSinkWriter.setSerializeNulls(true);
81 | bufferedSinkWriter.setLenient(true);
82 | OBJECT_ADAPTER.toJson(bufferedSinkWriter, writer.root());
83 | return buffer.readUtf8();
84 | } catch (IOException e) {
85 | throw new AssertionError();
86 | }
87 | }
88 |
89 | // TODO(jwilson): support BigDecimal and BigInteger and delete his method.
90 | @Override boolean supportsBigNumbers() {
91 | return false;
92 | }
93 |
94 | @Override public String toString() {
95 | return "Value";
96 | }
97 | };
98 |
99 | final JsonCodecFactory valuePeek = new JsonCodecFactory() {
100 | @Override public JsonReader newReader(String json) throws IOException {
101 | return value.newReader(json).peekJson();
102 | }
103 |
104 | // TODO(jwilson): fix precision checks and delete his method.
105 | @Override boolean implementsStrictPrecision() {
106 | return false;
107 | }
108 |
109 | @Override JsonWriter newWriter() {
110 | return value.newWriter();
111 | }
112 |
113 | @Override String json() {
114 | return value.json();
115 | }
116 |
117 | // TODO(jwilson): support BigDecimal and BigInteger and delete his method.
118 | @Override boolean supportsBigNumbers() {
119 | return false;
120 | }
121 |
122 | @Override public String toString() {
123 | return "ValuePeek";
124 | }
125 | };
126 |
127 | return Arrays.asList(
128 | new Object[] { utf8 },
129 | new Object[] { value },
130 | new Object[] { valuePeek });
131 | }
132 |
133 | abstract JsonReader newReader(String json) throws IOException;
134 |
135 | abstract JsonWriter newWriter();
136 |
137 | boolean implementsStrictPrecision() {
138 | return true;
139 | }
140 |
141 | abstract String json();
142 |
143 | boolean encodesToBytes() {
144 | return false;
145 | }
146 |
147 | boolean supportsBigNumbers() {
148 | return true;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/moshi/src/test/java/com/squareup/moshi/JsonReaderPathTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 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 | package com.squareup.moshi;
17 |
18 | import java.io.IOException;
19 | import java.util.List;
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.junit.runners.Parameterized;
23 | import org.junit.runners.Parameterized.Parameter;
24 | import org.junit.runners.Parameterized.Parameters;
25 |
26 | import static org.assertj.core.api.Assertions.assertThat;
27 | import static org.junit.Assume.assumeTrue;
28 |
29 | @RunWith(Parameterized.class)
30 | public final class JsonReaderPathTest {
31 | @Parameter public JsonCodecFactory factory;
32 |
33 | @Parameters(name = "{0}")
34 | public static List parameters() {
35 | return JsonCodecFactory.factories();
36 | }
37 |
38 | @SuppressWarnings("CheckReturnValue")
39 | @Test public void path() throws IOException {
40 | JsonReader reader = factory.newReader("{\"a\":[2,true,false,null,\"b\",{\"c\":\"d\"},[3]]}");
41 | assertThat(reader.getPath()).isEqualTo("$");
42 | reader.beginObject();
43 | assertThat(reader.getPath()).isEqualTo("$.");
44 | reader.nextName();
45 | assertThat(reader.getPath()).isEqualTo("$.a");
46 | reader.beginArray();
47 | assertThat(reader.getPath()).isEqualTo("$.a[0]");
48 | reader.nextInt();
49 | assertThat(reader.getPath()).isEqualTo("$.a[1]");
50 | reader.nextBoolean();
51 | assertThat(reader.getPath()).isEqualTo("$.a[2]");
52 | reader.nextBoolean();
53 | assertThat(reader.getPath()).isEqualTo("$.a[3]");
54 | reader.nextNull();
55 | assertThat(reader.getPath()).isEqualTo("$.a[4]");
56 | reader.nextString();
57 | assertThat(reader.getPath()).isEqualTo("$.a[5]");
58 | reader.beginObject();
59 | assertThat(reader.getPath()).isEqualTo("$.a[5].");
60 | reader.nextName();
61 | assertThat(reader.getPath()).isEqualTo("$.a[5].c");
62 | reader.nextString();
63 | assertThat(reader.getPath()).isEqualTo("$.a[5].c");
64 | reader.endObject();
65 | assertThat(reader.getPath()).isEqualTo("$.a[6]");
66 | reader.beginArray();
67 | assertThat(reader.getPath()).isEqualTo("$.a[6][0]");
68 | reader.nextInt();
69 | assertThat(reader.getPath()).isEqualTo("$.a[6][1]");
70 | reader.endArray();
71 | assertThat(reader.getPath()).isEqualTo("$.a[7]");
72 | reader.endArray();
73 | assertThat(reader.getPath()).isEqualTo("$.a");
74 | reader.endObject();
75 | assertThat(reader.getPath()).isEqualTo("$");
76 | }
77 |
78 | @Test public void arrayOfObjects() throws IOException {
79 | JsonReader reader = factory.newReader("[{},{},{}]");
80 | reader.beginArray();
81 | assertThat(reader.getPath()).isEqualTo("$[0]");
82 | reader.beginObject();
83 | assertThat(reader.getPath()).isEqualTo("$[0].");
84 | reader.endObject();
85 | assertThat(reader.getPath()).isEqualTo("$[1]");
86 | reader.beginObject();
87 | assertThat(reader.getPath()).isEqualTo("$[1].");
88 | reader.endObject();
89 | assertThat(reader.getPath()).isEqualTo("$[2]");
90 | reader.beginObject();
91 | assertThat(reader.getPath()).isEqualTo("$[2].");
92 | reader.endObject();
93 | assertThat(reader.getPath()).isEqualTo("$[3]");
94 | reader.endArray();
95 | assertThat(reader.getPath()).isEqualTo("$");
96 | }
97 |
98 | @Test public void arrayOfArrays() throws IOException {
99 | JsonReader reader = factory.newReader("[[],[],[]]");
100 | reader.beginArray();
101 | assertThat(reader.getPath()).isEqualTo("$[0]");
102 | reader.beginArray();
103 | assertThat(reader.getPath()).isEqualTo("$[0][0]");
104 | reader.endArray();
105 | assertThat(reader.getPath()).isEqualTo("$[1]");
106 | reader.beginArray();
107 | assertThat(reader.getPath()).isEqualTo("$[1][0]");
108 | reader.endArray();
109 | assertThat(reader.getPath()).isEqualTo("$[2]");
110 | reader.beginArray();
111 | assertThat(reader.getPath()).isEqualTo("$[2][0]");
112 | reader.endArray();
113 | assertThat(reader.getPath()).isEqualTo("$[3]");
114 | reader.endArray();
115 | assertThat(reader.getPath()).isEqualTo("$");
116 | }
117 |
118 | @SuppressWarnings("CheckReturnValue")
119 | @Test public void objectPath() throws IOException {
120 | JsonReader reader = factory.newReader("{\"a\":1,\"b\":2}");
121 | assertThat(reader.getPath()).isEqualTo("$");
122 |
123 | reader.peek();
124 | assertThat(reader.getPath()).isEqualTo("$");
125 | reader.beginObject();
126 | assertThat(reader.getPath()).isEqualTo("$.");
127 |
128 | reader.peek();
129 | assertThat(reader.getPath()).isEqualTo("$.");
130 | reader.nextName();
131 | assertThat(reader.getPath()).isEqualTo("$.a");
132 |
133 | reader.peek();
134 | assertThat(reader.getPath()).isEqualTo("$.a");
135 | reader.nextInt();
136 | assertThat(reader.getPath()).isEqualTo("$.a");
137 |
138 | reader.peek();
139 | assertThat(reader.getPath()).isEqualTo("$.a");
140 | reader.nextName();
141 | assertThat(reader.getPath()).isEqualTo("$.b");
142 |
143 | reader.peek();
144 | assertThat(reader.getPath()).isEqualTo("$.b");
145 | reader.nextInt();
146 | assertThat(reader.getPath()).isEqualTo("$.b");
147 |
148 | reader.peek();
149 | assertThat(reader.getPath()).isEqualTo("$.b");
150 | reader.endObject();
151 | assertThat(reader.getPath()).isEqualTo("$");
152 |
153 | reader.peek();
154 | assertThat(reader.getPath()).isEqualTo("$");
155 | reader.close();
156 | assertThat(reader.getPath()).isEqualTo("$");
157 | }
158 |
159 | @SuppressWarnings("CheckReturnValue")
160 | @Test public void arrayPath() throws IOException {
161 | JsonReader reader = factory.newReader("[1,2]");
162 | assertThat(reader.getPath()).isEqualTo("$");
163 |
164 | reader.peek();
165 | assertThat(reader.getPath()).isEqualTo("$");
166 | reader.beginArray();
167 | assertThat(reader.getPath()).isEqualTo("$[0]");
168 |
169 | reader.peek();
170 | assertThat(reader.getPath()).isEqualTo("$[0]");
171 | reader.nextInt();
172 | assertThat(reader.getPath()).isEqualTo("$[1]");
173 |
174 | reader.peek();
175 | assertThat(reader.getPath()).isEqualTo("$[1]");
176 | reader.nextInt();
177 | assertThat(reader.getPath()).isEqualTo("$[2]");
178 |
179 | reader.peek();
180 | assertThat(reader.getPath()).isEqualTo("$[2]");
181 | reader.endArray();
182 | assertThat(reader.getPath()).isEqualTo("$");
183 |
184 | reader.peek();
185 | assertThat(reader.getPath()).isEqualTo("$");
186 | reader.close();
187 | assertThat(reader.getPath()).isEqualTo("$");
188 | }
189 |
190 | @Test public void multipleTopLevelValuesInOneDocument() throws IOException {
191 | assumeTrue(factory.encodesToBytes());
192 |
193 | JsonReader reader = factory.newReader("[][]");
194 | reader.setLenient(true);
195 | reader.beginArray();
196 | reader.endArray();
197 | assertThat(reader.getPath()).isEqualTo("$");
198 | reader.beginArray();
199 | reader.endArray();
200 | assertThat(reader.getPath()).isEqualTo("$");
201 | }
202 |
203 | @Test public void skipArrayElements() throws IOException {
204 | JsonReader reader = factory.newReader("[1,2,3]");
205 | reader.beginArray();
206 | reader.skipValue();
207 | reader.skipValue();
208 | assertThat(reader.getPath()).isEqualTo("$[2]");
209 | }
210 |
211 | @Test public void skipObjectNames() throws IOException {
212 | JsonReader reader = factory.newReader("{\"a\":1}");
213 | reader.beginObject();
214 | reader.skipValue();
215 | assertThat(reader.getPath()).isEqualTo("$.null");
216 | }
217 |
218 | @SuppressWarnings("CheckReturnValue")
219 | @Test public void skipObjectValues() throws IOException {
220 | JsonReader reader = factory.newReader("{\"a\":1,\"b\":2}");
221 | reader.beginObject();
222 | reader.nextName();
223 | reader.skipValue();
224 | assertThat(reader.getPath()).isEqualTo("$.null");
225 | reader.nextName();
226 | assertThat(reader.getPath()).isEqualTo("$.b");
227 | }
228 |
229 | @Test public void skipNestedStructures() throws IOException {
230 | JsonReader reader = factory.newReader("[[1,2,3],4]");
231 | reader.beginArray();
232 | reader.skipValue();
233 | assertThat(reader.getPath()).isEqualTo("$[1]");
234 | }
235 | }
236 |
--------------------------------------------------------------------------------
/moshi/src/test/java/com/squareup/moshi/JsonUtf8WriterTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 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 | package com.squareup.moshi;
17 |
18 | import java.io.IOException;
19 | import okio.Buffer;
20 | import org.junit.Test;
21 |
22 | import static org.assertj.core.api.Assertions.assertThat;
23 |
24 | public final class JsonUtf8WriterTest {
25 | @Test public void prettyPrintObject() throws IOException {
26 | Buffer buffer = new Buffer();
27 | JsonWriter writer = JsonWriter.of(buffer);
28 | writer.setSerializeNulls(true);
29 | writer.setIndent(" ");
30 |
31 | writer.beginObject();
32 | writer.name("a").value(true);
33 | writer.name("b").value(false);
34 | writer.name("c").value(5.0);
35 | writer.name("e").nullValue();
36 | writer.name("f").beginArray();
37 | writer.value(6.0);
38 | writer.value(7.0);
39 | writer.endArray();
40 | writer.name("g").beginObject();
41 | writer.name("h").value(8.0);
42 | writer.name("i").value(9.0);
43 | writer.endObject();
44 | writer.endObject();
45 |
46 | String expected = "{\n"
47 | + " \"a\": true,\n"
48 | + " \"b\": false,\n"
49 | + " \"c\": 5.0,\n"
50 | + " \"e\": null,\n"
51 | + " \"f\": [\n"
52 | + " 6.0,\n"
53 | + " 7.0\n"
54 | + " ],\n"
55 | + " \"g\": {\n"
56 | + " \"h\": 8.0,\n"
57 | + " \"i\": 9.0\n"
58 | + " }\n"
59 | + "}";
60 | assertThat(buffer.readUtf8()).isEqualTo(expected);
61 | }
62 |
63 | @Test public void prettyPrintArray() throws IOException {
64 | Buffer buffer = new Buffer();
65 | JsonWriter writer = JsonWriter.of(buffer);
66 | writer.setIndent(" ");
67 |
68 | writer.beginArray();
69 | writer.value(true);
70 | writer.value(false);
71 | writer.value(5.0);
72 | writer.nullValue();
73 | writer.beginObject();
74 | writer.name("a").value(6.0);
75 | writer.name("b").value(7.0);
76 | writer.endObject();
77 | writer.beginArray();
78 | writer.value(8.0);
79 | writer.value(9.0);
80 | writer.endArray();
81 | writer.endArray();
82 |
83 | String expected = "[\n"
84 | + " true,\n"
85 | + " false,\n"
86 | + " 5.0,\n"
87 | + " null,\n"
88 | + " {\n"
89 | + " \"a\": 6.0,\n"
90 | + " \"b\": 7.0\n"
91 | + " },\n"
92 | + " [\n"
93 | + " 8.0,\n"
94 | + " 9.0\n"
95 | + " ]\n"
96 | + "]";
97 | assertThat(buffer.readUtf8()).isEqualTo(expected);
98 | }
99 |
100 | @Test public void repeatedNameIgnored() throws IOException {
101 | Buffer buffer = new Buffer();
102 | JsonWriter writer = JsonWriter.of(buffer);
103 | writer.beginObject();
104 | writer.name("a").value(1);
105 | writer.name("a").value(2);
106 | writer.endObject();
107 | // JsonWriter doesn't attempt to detect duplicate names
108 | assertThat(buffer.readUtf8()).isEqualTo("{\"a\":1,\"a\":2}");
109 | }
110 |
111 | @Test public void valueFromSource() throws IOException {
112 | Buffer buffer = new Buffer();
113 | JsonWriter writer = JsonUtf8Writer.of(buffer);
114 | writer.beginObject();
115 | writer.name("a");
116 | writer.value(new Buffer().writeUtf8("[\"value\"]"));
117 | writer.name("b");
118 | writer.value(new Buffer().writeUtf8("2"));
119 | writer.name("c");
120 | writer.value(3);
121 | writer.name("d");
122 | writer.value(new Buffer().writeUtf8("null"));
123 | writer.endObject();
124 | assertThat(buffer.readUtf8()).isEqualTo("{\"a\":[\"value\"],\"b\":2,\"c\":3,\"d\":null}");
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/moshi/src/test/java/com/squareup/moshi/RecursiveTypesResolveTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Gson Authors
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.squareup.moshi;
18 |
19 | import com.squareup.moshi.internal.Util;
20 | import org.junit.Test;
21 |
22 | import static org.junit.Assert.assertEquals;
23 | import static org.junit.Assert.assertNotNull;
24 |
25 | /**
26 | * Test fixes for infinite recursion on {@link Util#resolve(java.lang.reflect.Type, Class,
27 | * java.lang.reflect.Type)}, described at Issue #440
28 | * and similar issues.
29 | *
30 | * These tests originally caused {@link StackOverflowError} because of infinite recursion on attempts to
31 | * resolve generics on types, with an intermediate types like 'Foo2<? extends ? super ? extends ... ? extends A>'
32 | *
33 | * Adapted from https://github.com/google/gson/commit/a300148003e3a067875b1444e8268b6e0f0e0e02 in
34 | * service of https://github.com/square/moshi/issues/338.
35 | */
36 | public final class RecursiveTypesResolveTest {
37 |
38 | private static class Foo1 {
39 | public Foo2 extends A> foo2;
40 | }
41 |
42 | private static class Foo2 {
43 | public Foo1 super B> foo1;
44 | }
45 |
46 | /**
47 | * Test simplest case of recursion.
48 | */
49 | @Test public void recursiveResolveSimple() {
50 | JsonAdapter adapter = new Moshi.Builder().build().adapter(Foo1.class);
51 | assertNotNull(adapter);
52 | }
53 |
54 | //
55 | // Tests belows check the behaviour of the methods changed for the fix
56 | //
57 |
58 | @Test public void doubleSupertype() {
59 | assertEquals(Types.supertypeOf(Number.class),
60 | Types.supertypeOf(Types.supertypeOf(Number.class)));
61 | }
62 |
63 | @Test public void doubleSubtype() {
64 | assertEquals(Types.subtypeOf(Number.class),
65 | Types.subtypeOf(Types.subtypeOf(Number.class)));
66 | }
67 |
68 | @Test public void superSubtype() {
69 | assertEquals(Types.subtypeOf(Object.class),
70 | Types.supertypeOf(Types.subtypeOf(Number.class)));
71 | }
72 |
73 | @Test public void subSupertype() {
74 | assertEquals(Types.subtypeOf(Object.class),
75 | Types.subtypeOf(Types.supertypeOf(Number.class)));
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/moshi/src/test/java/com/squareup/moshi/TestUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square 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 | package com.squareup.moshi;
17 |
18 | import java.util.Arrays;
19 | import okio.Buffer;
20 |
21 | final class TestUtil {
22 | static final int MAX_DEPTH = 255;
23 |
24 | static JsonReader newReader(String json) {
25 | Buffer buffer = new Buffer().writeUtf8(json);
26 | return JsonReader.of(buffer);
27 | }
28 |
29 | static String repeat(char c, int count) {
30 | char[] array = new char[count];
31 | Arrays.fill(array, c);
32 | return new String(array);
33 | }
34 |
35 | static String repeat(String s, int count) {
36 | StringBuilder result = new StringBuilder(s.length() * count);
37 | for (int i = 0; i < count; i++) {
38 | result.append(s);
39 | }
40 | return result.toString();
41 | }
42 |
43 | private TestUtil() {
44 | throw new AssertionError("No instances.");
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4.0.0
5 |
6 |
7 | org.sonatype.oss
8 | oss-parent
9 | 7
10 |
11 |
12 | com.squareup.moshi
13 | moshi-parent
14 | 1.10.0-SNAPSHOT
15 | pom
16 | Moshi (Parent)
17 | A modern JSON API for Android and Java
18 | https://github.com/square/moshi
19 |
20 |
21 | moshi
22 | examples
23 | adapters
24 | kotlin/codegen
25 | kotlin/reflect
26 | kotlin/tests
27 |
28 |
29 |
30 | UTF-8
31 | 1.7
32 |
33 |
34 | 1.0-rc5
35 | 0.9.17
36 | 0.2
37 | 1.16.0
38 | 2.1.0
39 | 1.3.50
40 | 1.4.4
41 | 0.1.0
42 | 3.1.0
43 |
44 |
45 | 3.11.1
46 | 0.15
47 | 4.12
48 | 1.2.3
49 | 1.0
50 |
51 |
52 |
53 | https://github.com/square/moshi/
54 | scm:git:https://github.com/square/moshi.git
55 | scm:git:git@github.com:square/moshi.git
56 | HEAD
57 |
58 |
59 |
60 | GitHub Issues
61 | https://github.com/square/moshi/issues
62 |
63 |
64 |
65 |
66 | Apache 2.0
67 | http://www.apache.org/licenses/LICENSE-2.0.txt
68 |
69 |
70 |
71 |
72 |
73 |
74 | com.google.code.findbugs
75 | jsr305
76 | 3.0.2
77 | provided
78 |
79 |
80 | junit
81 | junit
82 | ${junit.version}
83 |
84 |
85 | com.squareup.okio
86 | okio
87 | ${okio.version}
88 |
89 |
90 | org.assertj
91 | assertj-core
92 | ${assertj.version}
93 |
94 |
95 | org.jetbrains.kotlin
96 | kotlin-stdlib
97 | ${kotlin.version}
98 |
99 |
100 | org.jetbrains.kotlin
101 | kotlin-reflect
102 | ${kotlin.version}
103 |
104 |
105 | org.jetbrains.kotlin
106 | kotlin-test
107 | ${kotlin.version}
108 | test
109 |
110 |
111 | org.jetbrains.kotlin
112 | kotlin-compiler-embeddable
113 | ${kotlin.version}
114 |
115 |
116 | org.jetbrains.kotlin
117 | kotlin-annotation-processing-embeddable
118 | ${kotlin.version}
119 |
120 |
121 | com.google.testing.compile
122 | compile-testing
123 | ${compile-testing.version}
124 |
125 |
126 |
127 |
128 |
129 |
130 | jcenter
131 | JCenter
132 | https://jcenter.bintray.com/
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 | org.apache.maven.plugins
141 | maven-compiler-plugin
142 | 3.8.1
143 |
144 | javac-with-errorprone
145 | true
146 | ${java.version}
147 | ${java.version}
148 |
149 |
150 |
151 | org.codehaus.plexus
152 | plexus-compiler-javac-errorprone
153 | 2.8
154 |
155 |
156 | com.google.errorprone
157 | error_prone_core
158 | 2.3.1
159 |
160 |
161 |
162 |
163 | org.jetbrains.kotlin
164 | kotlin-maven-plugin
165 | ${kotlin.version}
166 |
167 |
168 |
169 |
170 |
171 |
172 | org.apache.maven.plugins
173 | maven-checkstyle-plugin
174 | 2.17
175 |
176 |
177 | com.puppycrawl.tools
178 | checkstyle
179 | 7.7
180 |
181 |
182 |
183 | true
184 | checkstyle.xml
185 | true
186 | **/Iso8601Utils.java
187 |
188 |
189 |
190 | verify
191 |
192 | checkstyle
193 |
194 |
195 |
196 |
197 |
198 | org.apache.maven.plugins
199 | maven-release-plugin
200 | 2.5
201 |
202 | true
203 |
204 |
205 |
206 |
207 |
208 |
--------------------------------------------------------------------------------