diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..226a3f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +.classpath +.project +.settings +eclipsebin + +bin +gen +build +out +lib + +target +pom.xml.* +release.properties + +.idea +*.iml +*.ipr +*.iws +classes + +obj + +.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..1310bc9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +Change Log +========== + +## Version 0.1.0 + +_2014-08-09_ + + * Initial code creation. + * Imported JsonReader and JsonWriter from Gson. + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..54f63be --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,17 @@ +Contributing +============ + +If you would like to contribute code to Moshi you can do so through GitHub by +forking the repository and sending a pull request. + +When submitting code, please make every effort to follow existing conventions +and style in order to keep the code as readable as possible. Please also make +sure your code compiles by running `mvn clean verify`. Checkstyle failures +during compilation indicate errors in your style and can be viewed in the +`checkstyle-result.xml` file. + +Before your code can be accepted into the project you must also sign the +[Individual Contributor License Agreement (CLA)][1]. + + + [1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1 diff --git a/LICENSE b/LICENSE.txt similarity index 99% rename from LICENSE rename to LICENSE.txt index 5c304d1..d645695 100644 --- a/LICENSE +++ b/LICENSE.txt @@ -1,4 +1,5 @@ -Apache License + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -178,7 +179,7 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -186,7 +187,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index f7ef852..42e0415 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ -moshi +Moshi ===== + +A modern JSON library for Android and Java. + diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 0000000..794af42 --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deploy_javadoc.sh b/deploy_javadoc.sh new file mode 100755 index 0000000..c0eab59 --- /dev/null +++ b/deploy_javadoc.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +set -ex + +REPO="git@github.com:square/moshi.git" +GROUP_ID="com.squareup.moshi" +ARTIFACT_ID="moshi" + +DIR=temp-clone + +# Delete any existing temporary website clone +rm -rf $DIR + +# Clone the current repo into temp folder +git clone $REPO $DIR + +# Move working directory into temp folder +cd $DIR + +# Checkout and track the gh-pages branch +git checkout -t origin/gh-pages + +# Delete everything +rm -rf * + +# Download the latest javadoc +curl -L "http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=$GROUP_ID&a=$ARTIFACT_ID&v=LATEST&c=javadoc" > javadoc.zip +unzip javadoc.zip +rm javadoc.zip + +# Stage all files in git and create a commit +git add . +git add -u +git commit -m "Website at $(date)" + +# Push the new files up to GitHub +git push origin gh-pages + +# Delete our temp folder +cd .. +rm -rf $DIR diff --git a/moshi/pom.xml b/moshi/pom.xml new file mode 100644 index 0000000..dde3e73 --- /dev/null +++ b/moshi/pom.xml @@ -0,0 +1,27 @@ + + + + 4.0.0 + + + com.squareup.moshi + moshi-parent + 0.1-SNAPSHOT + + + moshi + Moshi + + + + com.squareup.okio + okio + 1.0.1 + + + junit + junit + test + + + diff --git a/moshi/src/main/java/com/squareup/moshi/JsonReader.java b/moshi/src/main/java/com/squareup/moshi/JsonReader.java new file mode 100644 index 0000000..93ac4de --- /dev/null +++ b/moshi/src/main/java/com/squareup/moshi/JsonReader.java @@ -0,0 +1,1592 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.squareup.moshi; + +import java.io.Closeable; +import java.io.EOFException; +import java.io.IOException; +import java.io.Reader; + +/** + * Reads a JSON (RFC 4627) + * encoded value as a stream of tokens. This stream includes both literal + * values (strings, numbers, booleans, and nulls) as well as the begin and + * end delimiters of objects and arrays. The tokens are traversed in + * depth-first order, the same order that they appear in the JSON document. + * Within JSON objects, name/value pairs are represented by a single token. + * + *

Parsing JSON

+ * To create a recursive descent parser for your own JSON streams, first create + * an entry point method that creates a {@code JsonReader}. + * + *

Next, create handler methods for each structure in your JSON text. You'll + * need a method for each object type and for each array type. + *

    + *
  • Within array handling methods, first call {@link + * #beginArray} to consume the array's opening bracket. Then create a + * while loop that accumulates values, terminating when {@link #hasNext} + * is false. Finally, read the array's closing bracket by calling {@link + * #endArray}. + *
  • Within object handling methods, first call {@link + * #beginObject} to consume the object's opening brace. Then create a + * while loop that assigns values to local variables based on their name. + * This loop should terminate when {@link #hasNext} is false. Finally, + * read the object's closing brace by calling {@link #endObject}. + *
+ *

When a nested object or array is encountered, delegate to the + * corresponding handler method. + * + *

When an unknown name is encountered, strict parsers should fail with an + * exception. Lenient parsers should call {@link #skipValue()} to recursively + * skip the value's nested tokens, which may otherwise conflict. + * + *

If a value may be null, you should first check using {@link #peek()}. + * Null literals can be consumed using either {@link #nextNull()} or {@link + * #skipValue()}. + * + *

Example

+ * Suppose we'd like to parse a stream of messages such as the following:
 {@code
+ * [
+ *   {
+ *     "id": 912345678901,
+ *     "text": "How do I read a JSON stream in Java?",
+ *     "geo": null,
+ *     "user": {
+ *       "name": "json_newb",
+ *       "followers_count": 41
+ *      }
+ *   },
+ *   {
+ *     "id": 912345678902,
+ *     "text": "@json_newb just use JsonReader!",
+ *     "geo": [50.454722, -104.606667],
+ *     "user": {
+ *       "name": "jesse",
+ *       "followers_count": 2
+ *     }
+ *   }
+ * ]}
+ * This code implements the parser for the above structure:
   {@code
+ *
+ *   public List readJsonStream(InputStream in) throws IOException {
+ *     JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
+ *     try {
+ *       return readMessagesArray(reader);
+ *     } finally {
+ *       reader.close();
+ *     }
+ *   }
+ *
+ *   public List readMessagesArray(JsonReader reader) throws IOException {
+ *     List messages = new ArrayList();
+ *
+ *     reader.beginArray();
+ *     while (reader.hasNext()) {
+ *       messages.add(readMessage(reader));
+ *     }
+ *     reader.endArray();
+ *     return messages;
+ *   }
+ *
+ *   public Message readMessage(JsonReader reader) throws IOException {
+ *     long id = -1;
+ *     String text = null;
+ *     User user = null;
+ *     List geo = null;
+ *
+ *     reader.beginObject();
+ *     while (reader.hasNext()) {
+ *       String name = reader.nextName();
+ *       if (name.equals("id")) {
+ *         id = reader.nextLong();
+ *       } else if (name.equals("text")) {
+ *         text = reader.nextString();
+ *       } else if (name.equals("geo") && reader.peek() != JsonToken.NULL) {
+ *         geo = readDoublesArray(reader);
+ *       } else if (name.equals("user")) {
+ *         user = readUser(reader);
+ *       } else {
+ *         reader.skipValue();
+ *       }
+ *     }
+ *     reader.endObject();
+ *     return new Message(id, text, user, geo);
+ *   }
+ *
+ *   public List readDoublesArray(JsonReader reader) throws IOException {
+ *     List doubles = new ArrayList();
+ *
+ *     reader.beginArray();
+ *     while (reader.hasNext()) {
+ *       doubles.add(reader.nextDouble());
+ *     }
+ *     reader.endArray();
+ *     return doubles;
+ *   }
+ *
+ *   public User readUser(JsonReader reader) throws IOException {
+ *     String username = null;
+ *     int followersCount = -1;
+ *
+ *     reader.beginObject();
+ *     while (reader.hasNext()) {
+ *       String name = reader.nextName();
+ *       if (name.equals("name")) {
+ *         username = reader.nextString();
+ *       } else if (name.equals("followers_count")) {
+ *         followersCount = reader.nextInt();
+ *       } else {
+ *         reader.skipValue();
+ *       }
+ *     }
+ *     reader.endObject();
+ *     return new User(username, followersCount);
+ *   }}
+ * + *

Number Handling

+ * This reader permits numeric values to be read as strings and string values to + * be read as numbers. For example, both elements of the JSON array {@code + * [1, "1"]} may be read using either {@link #nextInt} or {@link #nextString}. + * This behavior is intended to prevent lossy numeric conversions: double is + * JavaScript's only numeric type and very large values like {@code + * 9007199254740993} cannot be represented exactly on that platform. To minimize + * precision loss, extremely large values should be written and read as strings + * in JSON. + * + *

Non-Execute Prefix

+ * Web servers that serve private data using JSON may be vulnerable to
Cross-site + * request forgery attacks. In such an attack, a malicious site gains access + * to a private JSON file by executing it with an HTML {@code