├── .gitignore ├── JsonAnnotation.iml ├── README.md ├── Test Results - APIServiceTest.html ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── kale │ │ └── jsonannotation │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── kale │ │ │ └── jsonannotation │ │ │ ├── APIService.java │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── kale │ └── jsonannotation │ ├── APIServiceTest.java │ └── ExampleUnitTest.java ├── build.gradle ├── demo ├── api_json.png ├── build.png ├── code.png ├── json2Model.gif ├── jsonModel.png ├── lib.png ├── model.png └── rgb.jpg ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── lib ├── .gitignore ├── build.gradle ├── build │ └── libs │ │ └── lib.jar ├── lib.iml └── src │ └── main │ ├── java │ ├── com │ │ └── jsonformat │ │ │ ├── Config.java │ │ │ ├── FieldEntity.java │ │ │ ├── InnerClassEntity.java │ │ │ ├── JsonParserHelper.java │ │ │ └── Main.java │ ├── kale │ │ └── net │ │ │ └── json │ │ │ ├── annotation │ │ │ └── Json2Model.java │ │ │ └── processor │ │ │ └── Json2ModelProcessor.java │ └── org │ │ └── json │ │ ├── JSONArray.java │ │ ├── JSONException.java │ │ ├── JSONObject.java │ │ ├── JSONString.java │ │ └── JSONTokener.java │ └── resources │ └── META-INF │ ├── MANIFEST.MF │ └── services │ └── javax.annotation.processing.Processor └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | *.class 10 | .idea/workspace.xml 11 | 12 | # Mobile Tools for Java (J2ME) 13 | .mtj.tmp/ 14 | 15 | # Package Files # 16 | 17 | *.war 18 | *.ear 19 | 20 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 21 | hs_err_pid* 22 | 23 | # ========================= 24 | # Operating System Files 25 | # ========================= 26 | 27 | # OSX 28 | # ========================= 29 | 30 | .DS_Store 31 | .AppleDouble 32 | .LSOverride 33 | 34 | # Thumbnails 35 | ._* 36 | 37 | # Files that might appear on external disk 38 | .Spotlight-V100 39 | .Trashes 40 | 41 | # Directories potentially created on remote AFP share 42 | .AppleDB 43 | .AppleDesktop 44 | Network Trash Folder 45 | Temporary Items 46 | .apdisk 47 | 48 | # Windows 49 | # ========================= 50 | 51 | # Windows image file caches 52 | Thumbs.db 53 | ehthumbs.db 54 | 55 | # Folder config file 56 | Desktop.ini 57 | 58 | # Recycle Bin used on file shares 59 | $RECYCLE.BIN/ 60 | 61 | # Windows Installer files 62 | *.cab 63 | *.msi 64 | *.msm 65 | *.msp 66 | 67 | # Windows shortcuts 68 | *.lnk 69 | .idea/ 70 | gradle.properties 71 | gradle/wrapper/gradle-wrapper.jar 72 | -------------------------------------------------------------------------------- /JsonAnnotation.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JsonAnnotation 2 | JsonAnnotation can **speed up** Android development. 3 | It generates gson model class by json string automatically and lets you concentrate on what's really important. 4 | 5 | ### Demo 6 | 1.Copy url and json string into JsonAnnotation 7 | ![](./demo/api_json.png) 8 | 2.Just write a jsonModel name 9 | ![](./demo/jsonModel.png) 10 | 3.Build the project 11 | (->Make Project) 12 | ![](./demo/build.png) 13 | Then you can use UserInfo to do something~ 14 | 15 | **GIF Demo** 16 | Picture is big,wait a minute... 17 | ![](./demo/json2Model.gif) 18 | 19 | ### Usage 20 | 1.Add apt in **project's build.gradle** 21 | [apt][https://bitbucket.org/hvisser/android-apt] 22 | ``` 23 | dependencies { 24 | //... 25 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.7' 26 | } 27 | ``` 28 | 2.Add apt plugin below `apply plugin: 'com.android.application'` 29 | ``` 30 | apply plugin: 'android-apt' 31 | ``` 32 | 3.add jsonAnnotation.jar in lib 33 | ![](./demo/lib.png) 34 | 35 | Download Jar:[https://github.com/tianzhijiexian/JsonAnnotation/blob/master/lib/build/libs/lib.jar](https://github.com/tianzhijiexian/JsonAnnotation/blob/master/lib/build/libs/lib.jar) 36 | 37 | 38 | ### Question 39 | ```JAVA 40 | @Json2Model(modelName = "UserInfo",jsonStr = "{\n" 41 | + " \"id\": 100,\n" 42 | + " \"body\": \"It is my post\",\n" 43 | + " \"number\": 0.13,\n" 44 | + " \"created_at\": \"2014-05-22 19:12:38\"\n" 45 | + "}") 46 | String SEARCH_URSER_INFO = "search/user"; // api url 47 | ``` 48 | 49 | **1. Why we need build project?** 50 | Unfortunately,Android does not(yet)understand the concept of a compile-time-only dependency, so you need to mess with your build files to make it work. 51 | 52 | **2. Efficiency** 53 | @Json2Model will run in compile-time and models are created before generate apk file.Using JsonAnnotation,developers can let it generate the plumbing code at compile time.Reflect is not in this project,you needn't worry about efficiency questions. 54 | 55 | **3. Where are models** 56 | @Json2Model will create models is out of your own project.You can find theme in: 57 | `app(your model name)/build/generated/source/apt/debug/...` 58 | ![](./demo/model.png) 59 | You should edit these models by edit your jsonString. 60 | 61 | JsonAnnotation is less than 40kb,try it now~ 62 | 63 | similar project: [https://projectlombok.org/] 64 | 65 | ### Developer 66 | ![](https://avatars3.githubusercontent.com/u/9552155?v=3&s=460) 67 | Jack Tony: 68 | ![](https://avatars2.githubusercontent.com/u/5378647?v=3&s=200) 69 | zzz40500: 70 | 71 | ### License 72 | 73 | Copyright 2015 Jack Tony 74 | 75 | Licensed under the Apache License, Version 2.0 (the "License"); 76 | you may not use this file except in compliance with the License. 77 | You may obtain a copy of the License at 78 | 79 | http://www.apache.org/licenses/LICENSE-2.0 80 | 81 | Unless required by applicable law or agreed to in writing, software 82 | distributed under the License is distributed on an "AS IS" BASIS, 83 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 84 | See the License for the specific language governing permissions and 85 | limitations under the License. 86 | -------------------------------------------------------------------------------- /Test Results - APIServiceTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Results — APIServiceTest 6 | 278 | 279 | 282 | 322 | 556 | 570 | 571 | 572 | 573 |
574 | 590 |
591 |
    592 |
  • 593 | 594 |
    250 ms
    595 |
    APIServiceTest
    596 |
      597 |
    • 598 | 599 |
      246 ms
      600 |
      passedtest_nest
      601 |
    • 602 |
    • 603 | 604 |
      2 ms
      605 |
      passedtest_simple
      606 |
    • 607 |
    • 608 | 609 |
      2 ms
      610 |
      passedtest_array
      611 |
    • 612 |
    613 |
  • 614 |
615 |
616 |
617 | 620 | 621 | 622 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'android-apt' 3 | 4 | android { 5 | compileSdkVersion 23 6 | buildToolsVersion "23.0.0" 7 | 8 | defaultConfig { 9 | applicationId "kale.jsonannotation" 10 | minSdkVersion 14 11 | targetSdkVersion 23 12 | versionCode 1 13 | versionName "1.0" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | compileOptions { 22 | sourceCompatibility JavaVersion.VERSION_1_7 23 | targetCompatibility JavaVersion.VERSION_1_7 24 | } 25 | } 26 | 27 | dependencies { 28 | compile fileTree(include: ['*.jar'], dir: 'libs') 29 | compile project(':lib') 30 | 31 | compile 'com.android.support:appcompat-v7:23.0.0' 32 | compile 'com.google.code.gson:gson:2.3.1' 33 | testCompile 'junit:junit:4.12' 34 | } 35 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in H:\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/kale/jsonannotation/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package kale.jsonannotation; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | 11 | public ApplicationTest() { 12 | super(Application.class); 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/kale/jsonannotation/APIService.java: -------------------------------------------------------------------------------- 1 | package kale.jsonannotation; 2 | 3 | 4 | import kale.net.json.annotation.Json2Model; 5 | 6 | /** 7 | * @author Jack Tony 8 | * @date 2015/8/16 9 | * 这里我为了方便测试把jsonStr独立出来了 10 | */ 11 | public interface APIService { 12 | 13 | String simpleStr = "{\n" 14 | + " \"id\": 100,\n" 15 | + " \"body\": \"It is my post\",\n" 16 | + " \"number\": 0.13,\n" 17 | + " \"created_at\": \"2014-05-22 19:12:38\"\n" 18 | + "}"; 19 | // 简单格式 20 | @Json2Model(modelName = "Simple", jsonStr = simpleStr) 21 | String TEST_SIMPLE = "test/simple"; // api url 22 | 23 | 24 | String arrayStr = "[{\n" 25 | + " \"id\": 100,\n" 26 | + " \"body\": \"It is my post1\",\n" 27 | + " \"number\": 0.13,\n" 28 | + " \"created_at\": \"2014-05-20 19:12:38\"\n" 29 | + "},\n" 30 | + "{\n" 31 | + " \"id\": 101,\n" 32 | + " \"body\": \"It is my post2\",\n" 33 | + " \"number\": 0.14,\n" 34 | + " \"created_at\": \"2014-05-22 19:12:38\"\n" 35 | + "}]"; 36 | // 数组格式 37 | @Json2Model(modelName = "Array", jsonStr = arrayStr) 38 | String TEST_ARRAY = "test/array"; // api url 39 | 40 | String nestStr = "{\n" 41 | + " \"id\": 100,\n" 42 | + " \"body\": \"It is my post\",\n" 43 | + " \"number\": 0.13,\n" 44 | + " \"created_at\": \"2014-05-22 19:12:38\",\n" 45 | + " \"child\": {\n" 46 | + " \"id\": 200,\n" 47 | + " \"name\": \"haha\"\n" 48 | + " }\n" 49 | + "}"; 50 | // 嵌套类型 51 | @Json2Model(modelName = "Nest", jsonStr = nestStr) 52 | String TEST_NEST = "test/nest"; 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/kale/jsonannotation/MainActivity.java: -------------------------------------------------------------------------------- 1 | package kale.jsonannotation; 2 | 3 | 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | 8 | public class MainActivity extends AppCompatActivity { 9 | 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_main); 15 | 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | JsonAnnotation 3 | 4 | Hello world! 5 | Settings 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/test/java/kale/jsonannotation/APIServiceTest.java: -------------------------------------------------------------------------------- 1 | package kale.jsonannotation; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import org.junit.Test; 6 | 7 | import test.array.Array; 8 | import test.nest.Nest; 9 | import test.simple.Simple; 10 | 11 | import static org.junit.Assert.assertNotNull; 12 | 13 | /** 14 | * @author Jack Tony 15 | * @date 2015/8/22 16 | */ 17 | public class APIServiceTest { 18 | 19 | @Test 20 | public void test_simple() { 21 | Gson gson = new Gson(); 22 | Simple simple = gson.fromJson(APIService.simpleStr, Simple.class); 23 | assertNotNull(simple); 24 | assertNotNull(simple.getId()); 25 | assertNotNull(simple.getBody()); 26 | assertNotNull(simple.getNumber()); 27 | assertNotNull(simple.getCreatedAt()); 28 | } 29 | 30 | @Test 31 | public void test_array() { 32 | Gson gson = new Gson(); 33 | Array[] array = gson.fromJson(APIService.arrayStr, Array[].class); 34 | assertNotNull(array[0]); 35 | assertNotNull(array[0].getId()); 36 | assertNotNull(array[0].getBody()); 37 | assertNotNull(array[0].getNumber()); 38 | assertNotNull(array[0].getCreatedAt()); 39 | } 40 | 41 | @Test 42 | public void test_nest() { 43 | Gson gson = new Gson(); 44 | Nest nest = gson.fromJson(APIService.nestStr, Nest.class); 45 | assertNotNull(nest); 46 | assertNotNull(nest.getId()); 47 | assertNotNull(nest.getBody()); 48 | assertNotNull(nest.getNumber()); 49 | assertNotNull(nest.getCreatedAt()); 50 | assertNotNull(nest.getChild()); 51 | assertNotNull(nest.getChild().getId()); 52 | assertNotNull(nest.getChild().getName()); 53 | } 54 | 55 | 56 | } -------------------------------------------------------------------------------- /app/src/test/java/kale/jsonannotation/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package kale.jsonannotation; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | 12 | @Test 13 | public void addition_isCorrect() throws Exception { 14 | assertEquals(4, 2 + 2); 15 | } 16 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.3.0' 9 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.7' 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /demo/api_json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/demo/api_json.png -------------------------------------------------------------------------------- /demo/build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/demo/build.png -------------------------------------------------------------------------------- /demo/code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/demo/code.png -------------------------------------------------------------------------------- /demo/json2Model.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/demo/json2Model.gif -------------------------------------------------------------------------------- /demo/jsonModel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/demo/jsonModel.png -------------------------------------------------------------------------------- /demo/lib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/demo/lib.png -------------------------------------------------------------------------------- /demo/model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/demo/model.png -------------------------------------------------------------------------------- /demo/rgb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/demo/rgb.jpg -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 20 11:40:48 CST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | /build/tmp 2 | /build/resources 3 | -------------------------------------------------------------------------------- /lib/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | // thanks for http://stackoverflow.com/questions/24662801/bad-class-file-magic-or-version 4 | sourceCompatibility = 1.7 5 | targetCompatibility = 1.7 6 | 7 | dependencies { 8 | compile fileTree(dir: 'libs', include: ['*.jar']) 9 | } -------------------------------------------------------------------------------- /lib/build/libs/lib.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaleai/JsonAnnotation/9457f816b2ffba5f1117cf084e6b6414b27364b9/lib/build/libs/lib.jar -------------------------------------------------------------------------------- /lib/lib.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /lib/src/main/java/com/jsonformat/Config.java: -------------------------------------------------------------------------------- 1 | package com.jsonformat; 2 | 3 | 4 | /** 5 | * Created by zzz40500 on 15/5/31. 6 | * Ĭ�������� 7 | */ 8 | public class Config { 9 | 10 | private boolean fieldPrivateMode = true; 11 | 12 | private boolean useSerializedName = true; 13 | 14 | private String suffixStr = ""; 15 | 16 | private boolean resuseEntity = false; 17 | 18 | private Config() { 19 | 20 | } 21 | 22 | private static Config config; 23 | 24 | public static Config getInstant() { 25 | if (config == null) { 26 | config = new Config(); 27 | } 28 | return config; 29 | } 30 | 31 | 32 | public boolean isFieldPrivateMode() { 33 | return fieldPrivateMode; 34 | } 35 | 36 | 37 | public boolean isUseSerializedName() { 38 | return useSerializedName; 39 | } 40 | 41 | public String getSuffixStr() { 42 | return suffixStr; 43 | } 44 | 45 | public static Config getConfig() { 46 | return config; 47 | } 48 | 49 | public static void setConfig(Config config) { 50 | Config.config = config; 51 | } 52 | 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /lib/src/main/java/com/jsonformat/FieldEntity.java: -------------------------------------------------------------------------------- 1 | package com.jsonformat; 2 | 3 | /** 4 | * @author zwm 5 | * @version 2.0 6 | * @ClassName FieldEntity 7 | * @date 2015/8/14. 8 | */ 9 | public class FieldEntity { 10 | 11 | private String field; 12 | private String type; 13 | 14 | public String getField() { 15 | return field; 16 | } 17 | 18 | public void setField(String field) { 19 | this.field = field; 20 | } 21 | 22 | public String getType() { 23 | return type; 24 | } 25 | 26 | public void setType(String type) { 27 | this.type = type; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/main/java/com/jsonformat/InnerClassEntity.java: -------------------------------------------------------------------------------- 1 | package com.jsonformat; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by qingwei on 2015/8/19. 7 | */ 8 | public class InnerClassEntity { 9 | private String packName; 10 | private String className; 11 | private List fields; 12 | 13 | public String getPackName() { 14 | return packName; 15 | } 16 | 17 | public void setPackName(String packName) { 18 | this.packName = packName; 19 | } 20 | 21 | public String getClassName() { 22 | return className; 23 | } 24 | 25 | public void setClassName(String className) { 26 | this.className = className; 27 | } 28 | 29 | public List getFields() { 30 | return fields; 31 | } 32 | 33 | public void setFields(List fields) { 34 | this.fields = fields; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/main/java/com/jsonformat/JsonParserHelper.java: -------------------------------------------------------------------------------- 1 | package com.jsonformat; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONObject; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | public class JsonParserHelper { 12 | 13 | private List mKeyWordList; 14 | 15 | private List mFilterFields; 16 | 17 | private List mFilterClass; 18 | 19 | private StringBuilder mSB = new StringBuilder(); 20 | 21 | public JsonParserHelper() { 22 | mKeyWordList = new ArrayList<>(); 23 | mFilterFields = new ArrayList<>(); 24 | mFilterClass = new ArrayList<>(); 25 | } 26 | 27 | public interface ParseListener { 28 | 29 | void onParseComplete(String str); 30 | 31 | void onParseError(Exception e); 32 | } 33 | 34 | public void parse( String jsonStr, String rootClassName, ParseListener listener) { 35 | mSB.append("import com.google.gson.annotations.SerializedName;\n\n"); 36 | mSB.append("public class ").append(rootClassName).append(" {\n"); 37 | jsonStr = jsonStr.trim(); 38 | if (jsonStr.trim().startsWith("[")) { 39 | JSONArray jsonArray = new JSONArray(jsonStr); 40 | 41 | if (jsonArray.length() > 0 && jsonArray.get(0) instanceof JSONObject) { 42 | handleJsonObject(jsonArray.getJSONObject(0), listener); 43 | } 44 | } else if (jsonStr.trim().startsWith("{")) { 45 | JSONObject json = null; 46 | try { 47 | json = new JSONObject(jsonStr); 48 | } catch (Exception e) { 49 | String jsonTS = filterAnnotation(jsonStr); 50 | try { 51 | json = new JSONObject(jsonTS); 52 | } catch (Exception e2) { 53 | listener.onParseError(e2); 54 | } 55 | } 56 | 57 | handleJsonObject(json, listener); 58 | } 59 | 60 | } 61 | 62 | 63 | private void handleJsonObject(JSONObject json, ParseListener listener) { 64 | if (json != null) { 65 | try { 66 | parseJson(json, mSB); 67 | } catch (Exception e2) { 68 | listener.onParseError(e2); 69 | } 70 | } 71 | mKeyWordList = null; 72 | mFilterFields = null; 73 | mSB.append("}"); 74 | 75 | listener.onParseComplete(mSB.toString()); 76 | } 77 | 78 | 79 | // private void recursionInnerClass(InnerClassEntity innerClassEntity) { 80 | // PsiClass[] innerClass s = innerClassEntity.getPsiClass().getInnerClasses(); 81 | // if (innerClass s.length == 0) { 82 | // 83 | // mFilterClass.add(innerClassEntity); 84 | // } else { 85 | // for (PsiClass psiClass : innerClass s) { 86 | // InnerClassEntity innerClassEntity1 = new InnerClassEntity(); 87 | // innerClassEntity1.setClassName(psiClass.getName()); 88 | // innerClassEntity1.setFields(initFilterField(psiClass)); 89 | // innerClassEntity1.setPsiClass(psiClass); 90 | // innerClassEntity1.setPackName(innerClassEntity.getPackName() + innerClassEntity.getClassName() + "."); 91 | // recursionInnerClass(innerClassEntity1); 92 | // } 93 | // } 94 | // } 95 | 96 | 97 | public String filterAnnotation(String str) { 98 | 99 | String temp = str.replaceAll("/\\*" + 100 | "[\\S\\s]*?" + 101 | "\\*/", ""); 102 | return temp.replaceAll("//[\\S\\s]*?\n", ""); 103 | 104 | } 105 | 106 | 107 | public void parseJson(JSONObject json, StringBuilder stringBuilder) { 108 | 109 | 110 | //50 java keywords 111 | mKeyWordList.add("abstract"); 112 | mKeyWordList.add("assert"); 113 | mKeyWordList.add("boolean"); 114 | mKeyWordList.add("break"); 115 | mKeyWordList.add("byte"); 116 | mKeyWordList.add("case"); 117 | mKeyWordList.add("catch"); 118 | mKeyWordList.add("char"); 119 | mKeyWordList.add("class"); 120 | mKeyWordList.add("const"); 121 | mKeyWordList.add("continue"); 122 | mKeyWordList.add("default"); 123 | mKeyWordList.add("do"); 124 | mKeyWordList.add("double"); 125 | mKeyWordList.add("else"); 126 | mKeyWordList.add("enum"); 127 | mKeyWordList.add("extends"); 128 | mKeyWordList.add("final"); 129 | mKeyWordList.add("finally"); 130 | mKeyWordList.add("float"); 131 | mKeyWordList.add("for"); 132 | mKeyWordList.add("goto"); 133 | mKeyWordList.add("if"); 134 | mKeyWordList.add("implements"); 135 | mKeyWordList.add("import"); 136 | mKeyWordList.add("instanceof"); 137 | mKeyWordList.add("int"); 138 | mKeyWordList.add("interface"); 139 | mKeyWordList.add("long"); 140 | mKeyWordList.add("native"); 141 | mKeyWordList.add("new"); 142 | mKeyWordList.add("package"); 143 | mKeyWordList.add("private"); 144 | mKeyWordList.add("protected"); 145 | mKeyWordList.add("public"); 146 | mKeyWordList.add("return"); 147 | mKeyWordList.add("strictfp"); 148 | mKeyWordList.add("short"); 149 | mKeyWordList.add("static"); 150 | mKeyWordList.add("super"); 151 | mKeyWordList.add("switch"); 152 | mKeyWordList.add("synchronized"); 153 | mKeyWordList.add("this"); 154 | mKeyWordList.add("throw"); 155 | mKeyWordList.add("throws"); 156 | mKeyWordList.add("transient"); 157 | mKeyWordList.add("abstract"); 158 | mKeyWordList.add("void"); 159 | mKeyWordList.add("volatile"); 160 | mKeyWordList.add("while"); 161 | 162 | Set set = json.keySet(); 163 | 164 | List fieldList = new ArrayList<>(); 165 | for (String key : set) { 166 | if (!mFilterFields.contains(key)) { 167 | fieldList.add(key); 168 | } 169 | } 170 | InnerClassEntity classInnerClassEntity = new InnerClassEntity(); 171 | 172 | List fields = createField(classInnerClassEntity, json, fieldList, stringBuilder); 173 | FieldEntity fieldEntity = new FieldEntity(); 174 | 175 | if (Config.getInstant().isFieldPrivateMode()) { 176 | createSetMethod(fields, stringBuilder, fieldEntity); 177 | createGetMethod(fields, stringBuilder); 178 | } 179 | stringBuilder.append("\n"); 180 | } 181 | 182 | 183 | private List createField(InnerClassEntity innerClassEntity, JSONObject json, List list, StringBuilder stringBuilder) { 184 | List fieldEntities = new ArrayList<>(); 185 | StringBuilder sb = new StringBuilder(); 186 | 187 | for (int i = 0; i < list.size(); i++) { 188 | 189 | String key = list.get(i); 190 | Object type = json.get(key); 191 | StringBuilder filedSb = new StringBuilder(); 192 | 193 | String tabSpaceStr = " "; 194 | if (checkKeyWord(key)) { 195 | //是关键字 使用注解 196 | filedSb.append(tabSpaceStr).append("@SerializedName(\"").append(key).append("\")\n"); 197 | key = key + "X"; 198 | } else { 199 | if (Config.getInstant().isUseSerializedName()) { 200 | filedSb.append(tabSpaceStr).append("@SerializedName(\"").append(key).append("\")\n"); 201 | } 202 | } 203 | if (Config.getInstant().isUseSerializedName()) { 204 | key = captureStringLeaveUnderscore(key); 205 | } 206 | 207 | String typeStr = typeByValue(innerClassEntity, stringBuilder, key, type); 208 | // 配置是否是private(生成成员变量) 209 | if (Config.getInstant().isFieldPrivateMode()) { 210 | filedSb.append(tabSpaceStr).append("private").append(typeStr).append(key).append(";\n"); 211 | } else { 212 | filedSb.append(tabSpaceStr).append("public").append(typeStr).append(key).append(";\n"); 213 | } 214 | String filedStr; 215 | if (i == 0) { 216 | filedStr = sb.append(filedSb.toString()).toString(); 217 | } else { 218 | filedStr = filedSb.toString(); 219 | } 220 | FieldEntity fieldEntity = new FieldEntity(); 221 | fieldEntity.setField(key); 222 | fieldEntity.setType(typeStr); 223 | fieldEntities.add(fieldEntity); 224 | 225 | stringBuilder.append(filedStr).append("\n"); 226 | } 227 | return fieldEntities; 228 | } 229 | 230 | public boolean checkKeyWord(String key) { 231 | 232 | return mKeyWordList.contains(key); 233 | } 234 | 235 | 236 | private String typeByValue(InnerClassEntity innerClassEntity, StringBuilder stringBuilder, String key, Object type) { 237 | 238 | String typeStr; 239 | if (type instanceof Boolean) { 240 | typeStr = " boolean "; 241 | } else if (type instanceof Integer) { 242 | typeStr = " int "; 243 | } else if (type instanceof Double) { 244 | typeStr = " double "; 245 | } else if (type instanceof Long) { 246 | typeStr = " long "; 247 | } else if (type instanceof String) { 248 | typeStr = " String "; 249 | } else if (type instanceof JSONObject) { 250 | 251 | typeStr = checkInnerClass((JSONObject) type); 252 | 253 | if (typeStr == null) { 254 | typeStr = " " + createClassSubName(innerClassEntity, stringBuilder, key, type) + " "; 255 | createClassSub(innerClassEntity, typeStr, (JSONObject) type, stringBuilder); 256 | } else { 257 | typeStr = " " + typeStr + " "; 258 | } 259 | 260 | } else if (type instanceof JSONArray) { 261 | 262 | typeStr = " java.util.List<" + createClassSubName(innerClassEntity, stringBuilder, key, type) + "> "; 263 | 264 | } else { 265 | typeStr = " String "; 266 | } 267 | return typeStr; 268 | } 269 | 270 | private String checkInnerClass(JSONObject jsonObject) { 271 | 272 | for (InnerClassEntity InnerClassEntity : mFilterClass) { 273 | Iterator keys = jsonObject.keys(); 274 | 275 | boolean had = true; 276 | while (keys.hasNext()) { 277 | String key = keys.next(); 278 | if (!InnerClassEntity.getFields().contains(key)) { 279 | had = false; 280 | break; 281 | } 282 | } 283 | if (had) { 284 | 285 | if (InnerClassEntity.getPackName() != null) { 286 | return InnerClassEntity.getPackName() + "." + InnerClassEntity.getClassName(); 287 | } else { 288 | return InnerClassEntity.getClassName(); 289 | } 290 | } 291 | } 292 | return null; 293 | } 294 | 295 | 296 | private void createClassSub(InnerClassEntity parentC, String className, JSONObject json, StringBuilder sb) { 297 | 298 | sb.append("public static class ").append(className).append("{"); 299 | Set set = json.keySet(); 300 | List list = new ArrayList<>(set); 301 | 302 | InnerClassEntity innerClassEntity = new InnerClassEntity(); 303 | 304 | innerClassEntity.setClassName(className); 305 | if (parentC.getClassName() != null) { 306 | 307 | if (parentC.getPackName() == null) { 308 | innerClassEntity.setPackName(parentC.getClassName()); 309 | } else { 310 | innerClassEntity.setPackName(parentC.getPackName() + "." + parentC.getClassName()); 311 | } 312 | } 313 | 314 | 315 | List fields = createField(innerClassEntity, json, list, sb); 316 | if (Config.getInstant().isFieldPrivateMode()) { 317 | createSetMethod(fields, sb, null); 318 | createGetMethod(fields, sb); 319 | } 320 | sb.append("\n\n"); 321 | innerClassEntity.setFields(list); 322 | 323 | mFilterClass.add(innerClassEntity); 324 | 325 | 326 | sb.append("}\n"); 327 | } 328 | 329 | private String createClassSubName(InnerClassEntity innerClassEntity, StringBuilder sb, String key, Object o) { 330 | 331 | String name = ""; 332 | if (o instanceof JSONObject) { 333 | 334 | if (key == null || key.equals("")) { 335 | return key; 336 | } 337 | String[] strings = key.split("_"); 338 | StringBuilder stringBuilder = new StringBuilder(); 339 | for (String string : strings) { 340 | stringBuilder.append(captureName(string)); 341 | } 342 | 343 | name = stringBuilder.toString() + Config.getInstant().getSuffixStr(); 344 | 345 | } else if (o instanceof JSONArray) { 346 | JSONArray jsonArray = (JSONArray) o; 347 | if (jsonArray.length() > 0) { 348 | Object item = jsonArray.get(0); 349 | name = listTypeByValue(innerClassEntity, sb, key, item); 350 | } else { 351 | name = "?"; 352 | } 353 | } 354 | return name; 355 | } 356 | 357 | private String listTypeByValue(InnerClassEntity innerClassEntity, StringBuilder stringBuilder, String key, Object type) { 358 | 359 | String typeStr; 360 | 361 | 362 | if (type instanceof JSONObject) { 363 | 364 | typeStr = checkInnerClass((JSONObject) type); 365 | if (typeStr == null) { 366 | typeStr = createClassSubName(innerClassEntity, stringBuilder, key, type); 367 | createClassSub(innerClassEntity, typeStr, (JSONObject) type, stringBuilder); 368 | } 369 | 370 | } else if (type instanceof JSONArray) { 371 | typeStr = " java.util.List<" + createClassSubName(innerClassEntity, stringBuilder, key, type) + "> "; 372 | } else { 373 | 374 | 375 | typeStr = type.getClass().getSimpleName(); 376 | 377 | 378 | } 379 | return typeStr; 380 | } 381 | 382 | public String captureName(String name) { 383 | if (name.length() == 0) { 384 | return ""; 385 | } 386 | name = name.substring(0, 1).toUpperCase() + name.substring(1); 387 | 388 | return name; 389 | } 390 | 391 | public String captureStringLeaveUnderscore(String str) { 392 | if (str == null || "".equals(str)) { 393 | return str; 394 | } 395 | 396 | str = str.replaceAll("^_+", ""); 397 | String[] strings = str.split("_"); 398 | StringBuilder stringBuilder = new StringBuilder(); 399 | stringBuilder.append(strings[0]); 400 | for (int i = 1; i < strings.length; i++) { 401 | stringBuilder.append(captureName(strings[i])); 402 | } 403 | return stringBuilder.toString(); 404 | 405 | } 406 | 407 | private void createSetMethod(List fields, StringBuilder sb, FieldEntity fieldEntity) { 408 | for (FieldEntity field1 : fields) { 409 | String field = field1.getField(); 410 | String typeStr = field1.getType(); 411 | String method = "public void set" + captureName(field) + "( " + typeStr + " " + field + ") { this." + field + " = " + field + ";} "; 412 | sb.append(method); 413 | } 414 | } 415 | 416 | private void createGetMethod(List fields, StringBuilder sb) { 417 | 418 | for (FieldEntity field1 : fields) { 419 | String field = field1.getField(); 420 | 421 | String typeStr = field1.getType(); 422 | 423 | if (typeStr.equals(" boolean ")) { 424 | 425 | String method = "public " + typeStr + " is" + captureName(field) + "() { return " + field + ";} "; 426 | sb.append(method); 427 | } else { 428 | 429 | String method = "public " + typeStr + " get" + captureName(field) + "() { return " + field + ";} "; 430 | sb.append(method); 431 | } 432 | 433 | } 434 | } 435 | 436 | } 437 | -------------------------------------------------------------------------------- /lib/src/main/java/com/jsonformat/Main.java: -------------------------------------------------------------------------------- 1 | package com.jsonformat; 2 | 3 | public class Main { 4 | 5 | public static void main(String[] args) { 6 | String jsonStr; 7 | 8 | 9 | jsonStr = "{\n" + 10 | " \"name\": \"jack\",\n" + 11 | " \"gender\": \"man\",\n" + 12 | " \"age\": 15,\n" + 13 | " \"height\": \"140cm\",\n" + 14 | "}"; 15 | 16 | jsonStr = "{\n" + 17 | " \"name\": \"jack\",\n" + 18 | " \"gender\": \"man\",\n" + 19 | " \"age\": 15,\n" + 20 | " \"height\": \"140cm\",\n" + 21 | " \"addr\": {\n" + 22 | " \"province\": \"fujian\",\n" + 23 | " \"city\": \"quanzhou\",\n" + 24 | " \"code\": \"300000\"\n" + 25 | " },\n" + 26 | " \"hobby\": [\n" + 27 | " {\n" + 28 | " \"name\": \"billiards\",\n" + 29 | " \"code\": \"1\"\n" + 30 | " },\n" + 31 | " {\n" + 32 | " \"name\": \"computerGame\",\n" + 33 | " \"code\": \"2\"\n" + 34 | " }\n" + 35 | " ]\n" + 36 | "}"; 37 | 38 | jsonStr = "{\n" 39 | + " \"id\": 100,\n" 40 | + " \"body\": \"It is my post\",\n" 41 | + " \"number\": 0.13,\n" 42 | + " \"created_at\": \"2014-05-22 19:12:38\",\n" 43 | + " \"foo2\": {\n" 44 | + " \"id\": 200,\n" 45 | + " \"name\": \"haha\"\n" 46 | + " }\n" 47 | + "}"; 48 | 49 | jsonStr = "{\n" 50 | + " \"status\": 1,\n" 51 | + " \"data\": \n" 52 | + " {\n" 53 | + " \"more\": 1,\n" 54 | + " \"next_start\": 24,\n" 55 | + " \"object_list\": [{\n" 56 | + " \"photo\": \n" 57 | + " {\n" 58 | + " \"width\": 480,\n" 59 | + " \"height\": 698,\n" 60 | + " \"path\": \"http://cdn.duitang.com/uploads/item/201508/13/20150813235841_2FjJA.png\"\n" 61 | + " },\n" 62 | + " \"msg\": \"pվ\",\n" 63 | + " \"id\": 427355390,\n" 64 | + " \"buyable\": 0,\n" 65 | + " \"source_link\": \"\",\n" 66 | + " \"add_datetime\": \"23:58\",\n" 67 | + " \"add_datetime_pretty\": \"1Сʱǰ\",\n" 68 | + " \"add_datetime_ts\": 1439481522,\n" 69 | + " \"sender_id\": 8828896,\n" 70 | + " \"favorite_count\": 0,\n" 71 | + " \"extra_type\": \"PICTURE\"\n" 72 | + " }]\n" 73 | + " }\n" 74 | + "}"; 75 | jsonStr = "{\n" + 76 | "\"kind\": \"youtube#searchListResponse\",\n" + 77 | "\"etag\": \"\\\"k1sYjErg4tK7WaQQxvJkW5fVrfg/usRLzp_l5ss-L8Yb9ScY-VDAEOo\\\"\",\n" + 78 | "\"nextPageToken\": \"CAIQAA\",\n" + 79 | 80 | "\"pageInfo\": {\n" + 81 | "\"totalResults\": 1000000,\n" + 82 | "\"resultsPerPage\": 2\n" + 83 | "},\n" + 84 | "\"items\": [\n" + 85 | "{\n" + 86 | "\"kind\": \"youtube#searchResult\",\n" + 87 | "\"etag\": \"\\\"k1sYjErg4tK7WaQQxvJkW5fVrfg/D0nlqgSgFFEQnTduJtwcQZ3Hc78\\\"\",\n" + 88 | "\"id\": {\n" + 89 | "\"kind\": \"youtube#video\",\n" + 90 | "\"videoId\": \"5ixFWqZGZr8\"\n" + 91 | "},\n" + 92 | "\"snippet\": {\n" + 93 | "\"publishedAt\": \"2014-10-16T19:43:41.000Z\",\n" + 94 | "\"channelId\": \"UC9-3c4LzdzT_HvW3Xuti9wg\",\n" + 95 | "\"title\": \"Q&A WITH HARRY | PRANK CALLS!\",\n" + 96 | "\"description\": \"Can we smash 4000 likes for this Q&A!? My Flatmate Harold - http://www.youtube.com/W2S Buy Cheap and Instant Coins here: http://goo.gl/IZyNg2 Use code ...\",\n" + 97 | "\"thumbnails\": {\n" + 98 | "\"default\": {\n" + 99 | "\"url\": \"https://i.ytimg.com/vi/5ixFWqZGZr8/default.jpg\"\n" + 100 | "},\n" + 101 | "\"medium\": {\n" + 102 | "\"url\": \"https://i.ytimg.com/vi/5ixFWqZGZr8/mqdefault.jpg\"\n" + 103 | "},\n" + 104 | "\"high\": {\n" + 105 | "\"url\": \"https://i.ytimg.com/vi/5ixFWqZGZr8/hqdefault.jpg\"\n" + 106 | "}\n" + 107 | "},\n" + 108 | "\"channelTitle\": \"Calfreezy\",\n" + 109 | "\"liveBroadcastContent\": \"none\"\n" + 110 | "}\n" + 111 | "},\n" + 112 | "{\n" + 113 | "\"kind\": \"youtube#searchResult\",\n" + 114 | "\"etag\": \"\\\"k1sYjErg4tK7WaQQxvJkW5fVrfg/R5nmI-OBXmHyiXsGtMC3J6IUlBs\\\"\",\n" + 115 | "\"id\": {\n" + 116 | "\"kind\": \"youtube#video\",\n" + 117 | "\"videoId\": \"8KgzATFR0As\"\n" + 118 | "},\n" + 119 | "\"snippet\": {\n" + 120 | "\"publishedAt\": \"2014-09-03T12:49:15.000Z\",\n" + 121 | "\"channelId\": \"UC8_yRRDIGFaJEC7NOc1qTMw\",\n" + 122 | "\"title\": \"Harry at 30 Documentary\",\n" + 123 | "\"description\": \"In celebration of Prince Harry's 30th birthday, ITV have released a new documentary celebrating the past three decades of his life. Featuring archive footage...\",\n" + 124 | "\"thumbnails\": {\n" + 125 | "\"default\": {\n" + 126 | "\"url\": \"https://i.ytimg.com/vi/8KgzATFR0As/default.jpg\"\n" + 127 | "},\n" + 128 | "\"medium\": {\n" + 129 | "\"url\": \"https://i.ytimg.com/vi/8KgzATFR0As/mqdefault.jpg\"\n" + 130 | "},\n" + 131 | "\"high\": {\n" + 132 | "\"url\": \"https://i.ytimg.com/vi/8KgzATFR0As/hqdefault.jpg\"\n" + 133 | "}\n" + 134 | "},\n" + 135 | "\"channelTitle\": \"\",\n" + 136 | "\"liveBroadcastContent\": \"none\"\n" + 137 | "}\n" + 138 | "}\n" + 139 | "]\n" + 140 | ",\"zddd\": {\n" + 141 | "\"url\": \"https://i.ytimg.com/vi/8KgzATFR0As/default.jpg\"\n" + 142 | "},\n" + 143 | "}"; 144 | 145 | JsonParserHelper jsonParser = new JsonParserHelper(); 146 | 147 | jsonParser.parse(jsonStr, "RootClass", new JsonParserHelper.ParseListener() { 148 | @Override 149 | public void onParseComplete(String str) { 150 | System.out.println(str); 151 | } 152 | 153 | @Override 154 | public void onParseError(Exception e) { 155 | System.err.println(e.getMessage()); 156 | } 157 | }); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /lib/src/main/java/kale/net/json/annotation/Json2Model.java: -------------------------------------------------------------------------------- 1 | package kale.net.json.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * @author Jack Tony 11 | * @date 2015/8/13 12 | */ 13 | @Documented 14 | @Retention(RetentionPolicy.CLASS) 15 | @Target(ElementType.FIELD) 16 | public @interface Json2Model { 17 | 18 | String modelName(); 19 | 20 | String jsonStr(); 21 | 22 | // custom the model's package name 23 | String packageName() default ""; 24 | } 25 | -------------------------------------------------------------------------------- /lib/src/main/java/kale/net/json/processor/Json2ModelProcessor.java: -------------------------------------------------------------------------------- 1 | package kale.net.json.processor; 2 | 3 | import com.jsonformat.JsonParserHelper; 4 | 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | import java.io.OutputStreamWriter; 8 | import java.nio.charset.Charset; 9 | import java.util.Set; 10 | 11 | import javax.annotation.processing.AbstractProcessor; 12 | import javax.annotation.processing.ProcessingEnvironment; 13 | import javax.annotation.processing.RoundEnvironment; 14 | import javax.annotation.processing.SupportedAnnotationTypes; 15 | import javax.annotation.processing.SupportedSourceVersion; 16 | import javax.lang.model.SourceVersion; 17 | import javax.lang.model.element.Element; 18 | import javax.lang.model.element.TypeElement; 19 | import javax.lang.model.element.VariableElement; 20 | import javax.lang.model.util.Elements; 21 | import javax.tools.Diagnostic; 22 | import javax.tools.JavaFileObject; 23 | 24 | import kale.net.json.annotation.Json2Model; 25 | 26 | /** 27 | * @author Jack Tony 28 | * @date 2015/8/13 29 | */ 30 | @SupportedAnnotationTypes({"kale.net.json.annotation.Json2Model"}) 31 | @SupportedSourceVersion(SourceVersion.RELEASE_7) 32 | public class Json2ModelProcessor extends AbstractProcessor { 33 | 34 | private static final String TAG = "[ " + Json2Model.class.getSimpleName() + " ]:"; 35 | 36 | private Elements elementUtils; 37 | 38 | @Override 39 | public synchronized void init(ProcessingEnvironment processingEnv) { 40 | super.init(processingEnv); 41 | elementUtils = processingEnv.getElementUtils(); 42 | } 43 | 44 | private String packageName; 45 | 46 | @Override 47 | public boolean process(Set annotations, RoundEnvironment roundEnv) { 48 | for (TypeElement te : annotations) { 49 | for (Element e : roundEnv.getElementsAnnotatedWith(te)) { 50 | log("Working on: " + e.toString()); 51 | VariableElement varE = (VariableElement) e; 52 | 53 | Json2Model json2Model = e.getAnnotation(Json2Model.class); 54 | if (json2Model.packageName().equals("")) { 55 | // no custom package name 56 | /** 57 | * example: 58 | * String GET_USER_INFO = "create/info/user/info"; 59 | * result:create/info/user/info 60 | */ 61 | if (varE.getConstantValue() == null) { 62 | fatalError("jsonStr couldn't be final"); 63 | } 64 | String url = varE.getConstantValue().toString(); 65 | packageName = url2packageName(url); 66 | } else { 67 | // has custom package name 68 | packageName = json2Model.packageName(); 69 | } 70 | if (json2Model.jsonStr() == null || json2Model.jsonStr().equals("")) { 71 | fatalError("json string is null"); 72 | } 73 | 74 | final String clsName = json2Model.modelName(); 75 | 76 | JsonParserHelper helper = new JsonParserHelper(); 77 | helper.parse(json2Model.jsonStr(), clsName, new JsonParserHelper.ParseListener() { 78 | public void onParseComplete(String str) { 79 | createModelClass(packageName, clsName, "package " + packageName + ";\n" + str); 80 | } 81 | 82 | public void onParseError(Exception e) { 83 | e.printStackTrace(); 84 | fatalError(e.getMessage()); 85 | } 86 | }); 87 | log("Complete on: " + e.toString()); 88 | } 89 | } 90 | return true; 91 | } 92 | 93 | private void createModelClass(String packageName, String clsName, String content) { 94 | //PackageElement pkgElement = elementUtils.getPackageElement(""); 95 | TypeElement pkgElement = elementUtils.getTypeElement(packageName); 96 | 97 | OutputStreamWriter osw = null; 98 | try { 99 | // create a model file 100 | JavaFileObject fileObject = processingEnv.getFiler().createSourceFile(packageName + "." + clsName, pkgElement); 101 | OutputStream os = fileObject.openOutputStream(); 102 | osw = new OutputStreamWriter(os, Charset.forName("UTF-8")); 103 | osw.write(content, 0, content.length()); 104 | 105 | } catch (IOException e) { 106 | e.printStackTrace(); 107 | fatalError(e.getMessage()); 108 | } finally { 109 | try { 110 | if (osw != null) { 111 | osw.flush(); 112 | osw.close(); 113 | } 114 | } catch (IOException e) { 115 | e.printStackTrace(); 116 | fatalError(e.getMessage()); 117 | } 118 | } 119 | } 120 | 121 | private void log(String msg) { 122 | processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, TAG + msg); 123 | } 124 | 125 | private void fatalError(String msg) { 126 | processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, TAG + " FATAL ERROR: " + msg); 127 | } 128 | 129 | /** 130 | * /user/test/ - > user.test 131 | */ 132 | public static String url2packageName(String url) { 133 | String packageName = url.replaceAll("/", "."); 134 | if (packageName.startsWith(".")) { 135 | packageName = packageName.substring(1); 136 | } 137 | if (packageName.substring(packageName.length() - 1).equals(".")) { 138 | packageName = packageName.substring(0, packageName.length() - 1); 139 | } 140 | return packageName; 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /lib/src/main/java/org/json/JSONArray.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /* 4 | Copyright (c) 2002 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | import java.io.IOException; 28 | import java.io.StringWriter; 29 | import java.io.Writer; 30 | import java.lang.reflect.Array; 31 | import java.util.ArrayList; 32 | import java.util.Collection; 33 | import java.util.Iterator; 34 | import java.util.Map; 35 | 36 | /** 37 | * A JSONArray is an ordered sequence of values. Its external text form is a 38 | * string wrapped in square brackets with commas separating the values. The 39 | * internal form is an object having get and opt 40 | * methods for accessing the values by index, and put methods for 41 | * adding or replacing values. The values can be any of these types: 42 | * Boolean, JSONArray, JSONObject, 43 | * Number, String, or the 44 | * JSONObject.NULL object. 45 | *

46 | * The constructor can convert a JSON text into a Java object. The 47 | * toString method converts to JSON text. 48 | *

49 | * A get method returns a value if one can be found, and throws an 50 | * exception if one cannot be found. An opt method returns a 51 | * default value instead of throwing an exception, and so is useful for 52 | * obtaining optional values. 53 | *

54 | * The generic get() and opt() methods return an 55 | * object which you can cast or query for type. There are also typed 56 | * get and opt methods that do type checking and type 57 | * coercion for you. 58 | *

59 | * The texts produced by the toString methods strictly conform to 60 | * JSON syntax rules. The constructors are more forgiving in the texts they will 61 | * accept: 62 | *

    63 | *
  • An extra , (comma) may appear just 64 | * before the closing bracket.
  • 65 | *
  • The null value will be inserted when there is , 66 | *  (comma) elision.
  • 67 | *
  • Strings may be quoted with ' (single 68 | * quote).
  • 69 | *
  • Strings do not need to be quoted at all if they do not begin with a quote 70 | * or single quote, and if they do not contain leading or trailing spaces, and 71 | * if they do not contain any of these characters: 72 | * { } [ ] / \ : , # and if they do not look like numbers and 73 | * if they are not the reserved words true, false, or 74 | * null.
  • 75 | *
76 | * 77 | * @author JSON.org 78 | * @version 2014-05-03 79 | */ 80 | public class JSONArray { 81 | 82 | /** 83 | * The arrayList where the JSONArray's properties are kept. 84 | */ 85 | private final ArrayList myArrayList; 86 | 87 | /** 88 | * Construct an empty JSONArray. 89 | */ 90 | public JSONArray() { 91 | this.myArrayList = new ArrayList(); 92 | } 93 | 94 | /** 95 | * Construct a JSONArray from a JSONTokener. 96 | * 97 | * @param x 98 | * A JSONTokener 99 | * @throws JSONException 100 | * If there is a syntax error. 101 | */ 102 | public JSONArray(JSONTokener x) throws JSONException { 103 | this(); 104 | if (x.nextClean() != '[') { 105 | throw x.syntaxError("A JSONArray text must start with '['"); 106 | } 107 | if (x.nextClean() != ']') { 108 | x.back(); 109 | for (;;) { 110 | if (x.nextClean() == ',') { 111 | x.back(); 112 | this.myArrayList.add(JSONObject.NULL); 113 | } else { 114 | x.back(); 115 | this.myArrayList.add(x.nextValue()); 116 | } 117 | switch (x.nextClean()) { 118 | case ',': 119 | if (x.nextClean() == ']') { 120 | return; 121 | } 122 | x.back(); 123 | break; 124 | case ']': 125 | return; 126 | default: 127 | throw x.syntaxError("Expected a ',' or ']'"); 128 | } 129 | } 130 | } 131 | } 132 | 133 | /** 134 | * Construct a JSONArray from a source JSON text. 135 | * 136 | * @param source 137 | * A string that begins with [ (left 138 | * bracket) and ends with ] 139 | *  (right bracket). 140 | * @throws JSONException 141 | * If there is a syntax error. 142 | */ 143 | public JSONArray(String source) throws JSONException { 144 | this(new JSONTokener(source)); 145 | } 146 | 147 | /** 148 | * Construct a JSONArray from a Collection. 149 | * 150 | * @param collection 151 | * A Collection. 152 | */ 153 | public JSONArray(Collection collection) { 154 | this.myArrayList = new ArrayList(); 155 | if (collection != null) { 156 | Iterator iter = collection.iterator(); 157 | while (iter.hasNext()) { 158 | this.myArrayList.add(JSONObject.wrap(iter.next())); 159 | } 160 | } 161 | } 162 | 163 | /** 164 | * Construct a JSONArray from an array 165 | * 166 | * @throws JSONException 167 | * If not an array. 168 | */ 169 | public JSONArray(Object array) throws JSONException { 170 | this(); 171 | if (array.getClass().isArray()) { 172 | int length = Array.getLength(array); 173 | for (int i = 0; i < length; i += 1) { 174 | this.put(JSONObject.wrap(Array.get(array, i))); 175 | } 176 | } else { 177 | throw new JSONException( 178 | "JSONArray initial value should be a string or collection or array."); 179 | } 180 | } 181 | 182 | /** 183 | * Get the object value associated with an index. 184 | * 185 | * @param index 186 | * The index must be between 0 and length() - 1. 187 | * @return An object value. 188 | * @throws JSONException 189 | * If there is no value for the index. 190 | */ 191 | public Object get(int index) throws JSONException { 192 | Object object = this.opt(index); 193 | if (object == null) { 194 | throw new JSONException("JSONArray[" + index + "] not found."); 195 | } 196 | return object; 197 | } 198 | 199 | /** 200 | * Get the boolean value associated with an index. The string values "true" 201 | * and "false" are converted to boolean. 202 | * 203 | * @param index 204 | * The index must be between 0 and length() - 1. 205 | * @return The truth. 206 | * @throws JSONException 207 | * If there is no value for the index or if the value is not 208 | * convertible to boolean. 209 | */ 210 | public boolean getBoolean(int index) throws JSONException { 211 | Object object = this.get(index); 212 | if (object.equals(Boolean.FALSE) 213 | || (object instanceof String && ((String) object) 214 | .equalsIgnoreCase("false"))) { 215 | return false; 216 | } else if (object.equals(Boolean.TRUE) 217 | || (object instanceof String && ((String) object) 218 | .equalsIgnoreCase("true"))) { 219 | return true; 220 | } 221 | throw new JSONException("JSONArray[" + index + "] is not a boolean."); 222 | } 223 | 224 | /** 225 | * Get the double value associated with an index. 226 | * 227 | * @param index 228 | * The index must be between 0 and length() - 1. 229 | * @return The value. 230 | * @throws JSONException 231 | * If the key is not found or if the value cannot be converted 232 | * to a number. 233 | */ 234 | public double getDouble(int index) throws JSONException { 235 | Object object = this.get(index); 236 | try { 237 | return object instanceof Number ? ((Number) object).doubleValue() 238 | : Double.parseDouble((String) object); 239 | } catch (Exception e) { 240 | throw new JSONException("JSONArray[" + index + "] is not a number."); 241 | } 242 | } 243 | 244 | /** 245 | * Get the int value associated with an index. 246 | * 247 | * @param index 248 | * The index must be between 0 and length() - 1. 249 | * @return The value. 250 | * @throws JSONException 251 | * If the key is not found or if the value is not a number. 252 | */ 253 | public int getInt(int index) throws JSONException { 254 | Object object = this.get(index); 255 | try { 256 | return object instanceof Number ? ((Number) object).intValue() 257 | : Integer.parseInt((String) object); 258 | } catch (Exception e) { 259 | throw new JSONException("JSONArray[" + index + "] is not a number."); 260 | } 261 | } 262 | 263 | /** 264 | * Get the JSONArray associated with an index. 265 | * 266 | * @param index 267 | * The index must be between 0 and length() - 1. 268 | * @return A JSONArray value. 269 | * @throws JSONException 270 | * If there is no value for the index. or if the value is not a 271 | * JSONArray 272 | */ 273 | public JSONArray getJSONArray(int index) throws JSONException { 274 | Object object = this.get(index); 275 | if (object instanceof JSONArray) { 276 | return (JSONArray) object; 277 | } 278 | throw new JSONException("JSONArray[" + index + "] is not a JSONArray."); 279 | } 280 | 281 | /** 282 | * Get the JSONObject associated with an index. 283 | * 284 | * @param index 285 | * subscript 286 | * @return A JSONObject value. 287 | * @throws JSONException 288 | * If there is no value for the index or if the value is not a 289 | * JSONObject 290 | */ 291 | public JSONObject getJSONObject(int index) throws JSONException { 292 | Object object = this.get(index); 293 | if (object instanceof JSONObject) { 294 | return (JSONObject) object; 295 | } 296 | throw new JSONException("JSONArray[" + index + "] is not a JSONObject."); 297 | } 298 | 299 | /** 300 | * Get the long value associated with an index. 301 | * 302 | * @param index 303 | * The index must be between 0 and length() - 1. 304 | * @return The value. 305 | * @throws JSONException 306 | * If the key is not found or if the value cannot be converted 307 | * to a number. 308 | */ 309 | public long getLong(int index) throws JSONException { 310 | Object object = this.get(index); 311 | try { 312 | return object instanceof Number ? ((Number) object).longValue() 313 | : Long.parseLong((String) object); 314 | } catch (Exception e) { 315 | throw new JSONException("JSONArray[" + index + "] is not a number."); 316 | } 317 | } 318 | 319 | /** 320 | * Get the string associated with an index. 321 | * 322 | * @param index 323 | * The index must be between 0 and length() - 1. 324 | * @return A string value. 325 | * @throws JSONException 326 | * If there is no string value for the index. 327 | */ 328 | public String getString(int index) throws JSONException { 329 | Object object = this.get(index); 330 | if (object instanceof String) { 331 | return (String) object; 332 | } 333 | throw new JSONException("JSONArray[" + index + "] not a string."); 334 | } 335 | 336 | /** 337 | * Determine if the value is null. 338 | * 339 | * @param index 340 | * The index must be between 0 and length() - 1. 341 | * @return true if the value at the index is null, or if there is no value. 342 | */ 343 | public boolean isNull(int index) { 344 | return JSONObject.NULL.equals(this.opt(index)); 345 | } 346 | 347 | /** 348 | * Make a string from the contents of this JSONArray. The 349 | * separator string is inserted between each element. Warning: 350 | * This method assumes that the data structure is acyclical. 351 | * 352 | * @param separator 353 | * A string that will be inserted between the elements. 354 | * @return a string. 355 | * @throws JSONException 356 | * If the array contains an invalid number. 357 | */ 358 | public String join(String separator) throws JSONException { 359 | int len = this.length(); 360 | StringBuilder sb = new StringBuilder(); 361 | 362 | for (int i = 0; i < len; i += 1) { 363 | if (i > 0) { 364 | sb.append(separator); 365 | } 366 | sb.append(JSONObject.valueToString(this.myArrayList.get(i))); 367 | } 368 | return sb.toString(); 369 | } 370 | 371 | /** 372 | * Get the number of elements in the JSONArray, included nulls. 373 | * 374 | * @return The length (or size). 375 | */ 376 | public int length() { 377 | return this.myArrayList.size(); 378 | } 379 | 380 | /** 381 | * Get the optional object value associated with an index. 382 | * 383 | * @param index 384 | * The index must be between 0 and length() - 1. 385 | * @return An object value, or null if there is no object at that index. 386 | */ 387 | public Object opt(int index) { 388 | return (index < 0 || index >= this.length()) ? null : this.myArrayList 389 | .get(index); 390 | } 391 | 392 | /** 393 | * Get the optional boolean value associated with an index. It returns false 394 | * if there is no value at that index, or if the value is not Boolean.TRUE 395 | * or the String "true". 396 | * 397 | * @param index 398 | * The index must be between 0 and length() - 1. 399 | * @return The truth. 400 | */ 401 | public boolean optBoolean(int index) { 402 | return this.optBoolean(index, false); 403 | } 404 | 405 | /** 406 | * Get the optional boolean value associated with an index. It returns the 407 | * defaultValue if there is no value at that index or if it is not a Boolean 408 | * or the String "true" or "false" (case insensitive). 409 | * 410 | * @param index 411 | * The index must be between 0 and length() - 1. 412 | * @param defaultValue 413 | * A boolean default. 414 | * @return The truth. 415 | */ 416 | public boolean optBoolean(int index, boolean defaultValue) { 417 | try { 418 | return this.getBoolean(index); 419 | } catch (Exception e) { 420 | return defaultValue; 421 | } 422 | } 423 | 424 | /** 425 | * Get the optional double value associated with an index. NaN is returned 426 | * if there is no value for the index, or if the value is not a number and 427 | * cannot be converted to a number. 428 | * 429 | * @param index 430 | * The index must be between 0 and length() - 1. 431 | * @return The value. 432 | */ 433 | public double optDouble(int index) { 434 | return this.optDouble(index, Double.NaN); 435 | } 436 | 437 | /** 438 | * Get the optional double value associated with an index. The defaultValue 439 | * is returned if there is no value for the index, or if the value is not a 440 | * number and cannot be converted to a number. 441 | * 442 | * @param index 443 | * subscript 444 | * @param defaultValue 445 | * The default value. 446 | * @return The value. 447 | */ 448 | public double optDouble(int index, double defaultValue) { 449 | try { 450 | return this.getDouble(index); 451 | } catch (Exception e) { 452 | return defaultValue; 453 | } 454 | } 455 | 456 | /** 457 | * Get the optional int value associated with an index. Zero is returned if 458 | * there is no value for the index, or if the value is not a number and 459 | * cannot be converted to a number. 460 | * 461 | * @param index 462 | * The index must be between 0 and length() - 1. 463 | * @return The value. 464 | */ 465 | public int optInt(int index) { 466 | return this.optInt(index, 0); 467 | } 468 | 469 | /** 470 | * Get the optional int value associated with an index. The defaultValue is 471 | * returned if there is no value for the index, or if the value is not a 472 | * number and cannot be converted to a number. 473 | * 474 | * @param index 475 | * The index must be between 0 and length() - 1. 476 | * @param defaultValue 477 | * The default value. 478 | * @return The value. 479 | */ 480 | public int optInt(int index, int defaultValue) { 481 | try { 482 | return this.getInt(index); 483 | } catch (Exception e) { 484 | return defaultValue; 485 | } 486 | } 487 | 488 | /** 489 | * Get the optional JSONArray associated with an index. 490 | * 491 | * @param index 492 | * subscript 493 | * @return A JSONArray value, or null if the index has no value, or if the 494 | * value is not a JSONArray. 495 | */ 496 | public JSONArray optJSONArray(int index) { 497 | Object o = this.opt(index); 498 | return o instanceof JSONArray ? (JSONArray) o : null; 499 | } 500 | 501 | /** 502 | * Get the optional JSONObject associated with an index. Null is returned if 503 | * the key is not found, or null if the index has no value, or if the value 504 | * is not a JSONObject. 505 | * 506 | * @param index 507 | * The index must be between 0 and length() - 1. 508 | * @return A JSONObject value. 509 | */ 510 | public JSONObject optJSONObject(int index) { 511 | Object o = this.opt(index); 512 | return o instanceof JSONObject ? (JSONObject) o : null; 513 | } 514 | 515 | /** 516 | * Get the optional long value associated with an index. Zero is returned if 517 | * there is no value for the index, or if the value is not a number and 518 | * cannot be converted to a number. 519 | * 520 | * @param index 521 | * The index must be between 0 and length() - 1. 522 | * @return The value. 523 | */ 524 | public long optLong(int index) { 525 | return this.optLong(index, 0); 526 | } 527 | 528 | /** 529 | * Get the optional long value associated with an index. The defaultValue is 530 | * returned if there is no value for the index, or if the value is not a 531 | * number and cannot be converted to a number. 532 | * 533 | * @param index 534 | * The index must be between 0 and length() - 1. 535 | * @param defaultValue 536 | * The default value. 537 | * @return The value. 538 | */ 539 | public long optLong(int index, long defaultValue) { 540 | try { 541 | return this.getLong(index); 542 | } catch (Exception e) { 543 | return defaultValue; 544 | } 545 | } 546 | 547 | /** 548 | * Get the optional string value associated with an index. It returns an 549 | * empty string if there is no value at that index. If the value is not a 550 | * string and is not null, then it is coverted to a string. 551 | * 552 | * @param index 553 | * The index must be between 0 and length() - 1. 554 | * @return A String value. 555 | */ 556 | public String optString(int index) { 557 | return this.optString(index, ""); 558 | } 559 | 560 | /** 561 | * Get the optional string associated with an index. The defaultValue is 562 | * returned if the key is not found. 563 | * 564 | * @param index 565 | * The index must be between 0 and length() - 1. 566 | * @param defaultValue 567 | * The default value. 568 | * @return A String value. 569 | */ 570 | public String optString(int index, String defaultValue) { 571 | Object object = this.opt(index); 572 | return JSONObject.NULL.equals(object) ? defaultValue : object 573 | .toString(); 574 | } 575 | 576 | /** 577 | * Append a boolean value. This increases the array's length by one. 578 | * 579 | * @param value 580 | * A boolean value. 581 | * @return this. 582 | */ 583 | public JSONArray put(boolean value) { 584 | this.put(value ? Boolean.TRUE : Boolean.FALSE); 585 | return this; 586 | } 587 | 588 | /** 589 | * Put a value in the JSONArray, where the value will be a JSONArray which 590 | * is produced from a Collection. 591 | * 592 | * @param value 593 | * A Collection value. 594 | * @return this. 595 | */ 596 | public JSONArray put(Collection value) { 597 | this.put(new JSONArray(value)); 598 | return this; 599 | } 600 | 601 | /** 602 | * Append a double value. This increases the array's length by one. 603 | * 604 | * @param value 605 | * A double value. 606 | * @throws JSONException 607 | * if the value is not finite. 608 | * @return this. 609 | */ 610 | public JSONArray put(double value) throws JSONException { 611 | Double d = new Double(value); 612 | JSONObject.testValidity(d); 613 | this.put(d); 614 | return this; 615 | } 616 | 617 | /** 618 | * Append an int value. This increases the array's length by one. 619 | * 620 | * @param value 621 | * An int value. 622 | * @return this. 623 | */ 624 | public JSONArray put(int value) { 625 | this.put(new Integer(value)); 626 | return this; 627 | } 628 | 629 | /** 630 | * Append an long value. This increases the array's length by one. 631 | * 632 | * @param value 633 | * A long value. 634 | * @return this. 635 | */ 636 | public JSONArray put(long value) { 637 | this.put(new Long(value)); 638 | return this; 639 | } 640 | 641 | /** 642 | * Put a value in the JSONArray, where the value will be a JSONObject which 643 | * is produced from a Map. 644 | * 645 | * @param value 646 | * A Map value. 647 | * @return this. 648 | */ 649 | public JSONArray put(Map value) { 650 | this.put(new JSONObject(value)); 651 | return this; 652 | } 653 | 654 | /** 655 | * Append an object value. This increases the array's length by one. 656 | * 657 | * @param value 658 | * An object value. The value should be a Boolean, Double, 659 | * Integer, JSONArray, JSONObject, Long, or String, or the 660 | * JSONObject.NULL object. 661 | * @return this. 662 | */ 663 | public JSONArray put(Object value) { 664 | this.myArrayList.add(value); 665 | return this; 666 | } 667 | 668 | /** 669 | * Put or replace a boolean value in the JSONArray. If the index is greater 670 | * than the length of the JSONArray, then null elements will be added as 671 | * necessary to pad it out. 672 | * 673 | * @param index 674 | * The subscript. 675 | * @param value 676 | * A boolean value. 677 | * @return this. 678 | * @throws JSONException 679 | * If the index is negative. 680 | */ 681 | public JSONArray put(int index, boolean value) throws JSONException { 682 | this.put(index, value ? Boolean.TRUE : Boolean.FALSE); 683 | return this; 684 | } 685 | 686 | /** 687 | * Put a value in the JSONArray, where the value will be a JSONArray which 688 | * is produced from a Collection. 689 | * 690 | * @param index 691 | * The subscript. 692 | * @param value 693 | * A Collection value. 694 | * @return this. 695 | * @throws JSONException 696 | * If the index is negative or if the value is not finite. 697 | */ 698 | public JSONArray put(int index, Collection value) throws JSONException { 699 | this.put(index, new JSONArray(value)); 700 | return this; 701 | } 702 | 703 | /** 704 | * Put or replace a double value. If the index is greater than the length of 705 | * the JSONArray, then null elements will be added as necessary to pad it 706 | * out. 707 | * 708 | * @param index 709 | * The subscript. 710 | * @param value 711 | * A double value. 712 | * @return this. 713 | * @throws JSONException 714 | * If the index is negative or if the value is not finite. 715 | */ 716 | public JSONArray put(int index, double value) throws JSONException { 717 | this.put(index, new Double(value)); 718 | return this; 719 | } 720 | 721 | /** 722 | * Put or replace an int value. If the index is greater than the length of 723 | * the JSONArray, then null elements will be added as necessary to pad it 724 | * out. 725 | * 726 | * @param index 727 | * The subscript. 728 | * @param value 729 | * An int value. 730 | * @return this. 731 | * @throws JSONException 732 | * If the index is negative. 733 | */ 734 | public JSONArray put(int index, int value) throws JSONException { 735 | this.put(index, new Integer(value)); 736 | return this; 737 | } 738 | 739 | /** 740 | * Put or replace a long value. If the index is greater than the length of 741 | * the JSONArray, then null elements will be added as necessary to pad it 742 | * out. 743 | * 744 | * @param index 745 | * The subscript. 746 | * @param value 747 | * A long value. 748 | * @return this. 749 | * @throws JSONException 750 | * If the index is negative. 751 | */ 752 | public JSONArray put(int index, long value) throws JSONException { 753 | this.put(index, new Long(value)); 754 | return this; 755 | } 756 | 757 | /** 758 | * Put a value in the JSONArray, where the value will be a JSONObject that 759 | * is produced from a Map. 760 | * 761 | * @param index 762 | * The subscript. 763 | * @param value 764 | * The Map value. 765 | * @return this. 766 | * @throws JSONException 767 | * If the index is negative or if the the value is an invalid 768 | * number. 769 | */ 770 | public JSONArray put(int index, Map value) throws JSONException { 771 | this.put(index, new JSONObject(value)); 772 | return this; 773 | } 774 | 775 | /** 776 | * Put or replace an object value in the JSONArray. If the index is greater 777 | * than the length of the JSONArray, then null elements will be added as 778 | * necessary to pad it out. 779 | * 780 | * @param index 781 | * The subscript. 782 | * @param value 783 | * The value to put into the array. The value should be a 784 | * Boolean, Double, Integer, JSONArray, JSONObject, Long, or 785 | * String, or the JSONObject.NULL object. 786 | * @return this. 787 | * @throws JSONException 788 | * If the index is negative or if the the value is an invalid 789 | * number. 790 | */ 791 | public JSONArray put(int index, Object value) throws JSONException { 792 | JSONObject.testValidity(value); 793 | if (index < 0) { 794 | throw new JSONException("JSONArray[" + index + "] not found."); 795 | } 796 | if (index < this.length()) { 797 | this.myArrayList.set(index, value); 798 | } else { 799 | while (index != this.length()) { 800 | this.put(JSONObject.NULL); 801 | } 802 | this.put(value); 803 | } 804 | return this; 805 | } 806 | 807 | /** 808 | * Remove an index and close the hole. 809 | * 810 | * @param index 811 | * The index of the element to be removed. 812 | * @return The value that was associated with the index, or null if there 813 | * was no value. 814 | */ 815 | public Object remove(int index) { 816 | return index >= 0 && index < this.length() 817 | ? this.myArrayList.remove(index) 818 | : null; 819 | } 820 | 821 | /** 822 | * Determine if two JSONArrays are similar. 823 | * They must contain similar sequences. 824 | * 825 | * @param other The other JSONArray 826 | * @return true if they are equal 827 | */ 828 | public boolean similar(Object other) { 829 | if (!(other instanceof JSONArray)) { 830 | return false; 831 | } 832 | int len = this.length(); 833 | if (len != ((JSONArray)other).length()) { 834 | return false; 835 | } 836 | for (int i = 0; i < len; i += 1) { 837 | Object valueThis = this.get(i); 838 | Object valueOther = ((JSONArray)other).get(i); 839 | if (valueThis instanceof JSONObject) { 840 | if (!((JSONObject)valueThis).similar(valueOther)) { 841 | return false; 842 | } 843 | } else if (valueThis instanceof JSONArray) { 844 | if (!((JSONArray)valueThis).similar(valueOther)) { 845 | return false; 846 | } 847 | } else if (!valueThis.equals(valueOther)) { 848 | return false; 849 | } 850 | } 851 | return true; 852 | } 853 | 854 | /** 855 | * Produce a JSONObject by combining a JSONArray of names with the values of 856 | * this JSONArray. 857 | * 858 | * @param names 859 | * A JSONArray containing a list of key strings. These will be 860 | * paired with the values. 861 | * @return A JSONObject, or null if there are no names or if this JSONArray 862 | * has no values. 863 | * @throws JSONException 864 | * If any of the names are null. 865 | */ 866 | public JSONObject toJSONObject(JSONArray names) throws JSONException { 867 | if (names == null || names.length() == 0 || this.length() == 0) { 868 | return null; 869 | } 870 | JSONObject jo = new JSONObject(); 871 | for (int i = 0; i < names.length(); i += 1) { 872 | jo.put(names.getString(i), this.opt(i)); 873 | } 874 | return jo; 875 | } 876 | 877 | /** 878 | * Make a JSON text of this JSONArray. For compactness, no unnecessary 879 | * whitespace is added. If it is not possible to produce a syntactically 880 | * correct JSON text then null will be returned instead. This could occur if 881 | * the array contains an invalid number. 882 | *

883 | * Warning: This method assumes that the data structure is acyclical. 884 | * 885 | * @return a printable, displayable, transmittable representation of the 886 | * array. 887 | */ 888 | public String toString() { 889 | try { 890 | return this.toString(0); 891 | } catch (Exception e) { 892 | return null; 893 | } 894 | } 895 | 896 | /** 897 | * Make a prettyprinted JSON text of this JSONArray. Warning: This method 898 | * assumes that the data structure is acyclical. 899 | * 900 | * @param indentFactor 901 | * The number of spaces to add to each level of indentation. 902 | * @return a printable, displayable, transmittable representation of the 903 | * object, beginning with [ (left 904 | * bracket) and ending with ] 905 | *  (right bracket). 906 | * @throws JSONException 907 | */ 908 | public String toString(int indentFactor) throws JSONException { 909 | StringWriter sw = new StringWriter(); 910 | synchronized (sw.getBuffer()) { 911 | return this.write(sw, indentFactor, 0).toString(); 912 | } 913 | } 914 | 915 | /** 916 | * Write the contents of the JSONArray as JSON text to a writer. For 917 | * compactness, no whitespace is added. 918 | *

919 | * Warning: This method assumes that the data structure is acyclical. 920 | * 921 | * @return The writer. 922 | * @throws JSONException 923 | */ 924 | public Writer write(Writer writer) throws JSONException { 925 | return this.write(writer, 0, 0); 926 | } 927 | 928 | /** 929 | * Write the contents of the JSONArray as JSON text to a writer. For 930 | * compactness, no whitespace is added. 931 | *

932 | * Warning: This method assumes that the data structure is acyclical. 933 | * 934 | * @param indentFactor 935 | * The number of spaces to add to each level of indentation. 936 | * @param indent 937 | * The indention of the top level. 938 | * @return The writer. 939 | * @throws JSONException 940 | */ 941 | Writer write(Writer writer, int indentFactor, int indent) 942 | throws JSONException { 943 | try { 944 | boolean commanate = false; 945 | int length = this.length(); 946 | writer.write('['); 947 | 948 | if (length == 1) { 949 | JSONObject.writeValue(writer, this.myArrayList.get(0), 950 | indentFactor, indent); 951 | } else if (length != 0) { 952 | final int newindent = indent + indentFactor; 953 | 954 | for (int i = 0; i < length; i += 1) { 955 | if (commanate) { 956 | writer.write(','); 957 | } 958 | if (indentFactor > 0) { 959 | writer.write('\n'); 960 | } 961 | JSONObject.indent(writer, newindent); 962 | JSONObject.writeValue(writer, this.myArrayList.get(i), 963 | indentFactor, newindent); 964 | commanate = true; 965 | } 966 | if (indentFactor > 0) { 967 | writer.write('\n'); 968 | } 969 | JSONObject.indent(writer, indent); 970 | } 971 | writer.write(']'); 972 | return writer; 973 | } catch (IOException e) { 974 | throw new JSONException(e); 975 | } 976 | } 977 | } 978 | -------------------------------------------------------------------------------- /lib/src/main/java/org/json/JSONException.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /** 4 | * The JSONException is thrown by the JSON.org classes when things are amiss. 5 | * 6 | * @author JSON.org 7 | * @version 2014-05-03 8 | */ 9 | public class JSONException extends RuntimeException { 10 | private static final long serialVersionUID = 0; 11 | private Throwable cause; 12 | 13 | /** 14 | * Constructs a JSONException with an explanatory message. 15 | * 16 | * @param message 17 | * Detail about the reason for the exception. 18 | */ 19 | public JSONException(String message) { 20 | super(message); 21 | } 22 | 23 | /** 24 | * Constructs a new JSONException with the specified cause. 25 | * @param cause The cause. 26 | */ 27 | public JSONException(Throwable cause) { 28 | super(cause.getMessage()); 29 | this.cause = cause; 30 | } 31 | 32 | /** 33 | * Returns the cause of this exception or null if the cause is nonexistent 34 | * or unknown. 35 | * 36 | * @return the cause of this exception or null if the cause is nonexistent 37 | * or unknown. 38 | */ 39 | @Override 40 | public Throwable getCause() { 41 | return this.cause; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/src/main/java/org/json/JSONString.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | /** 3 | * The JSONString interface allows a toJSONString() 4 | * method so that a class can change the behavior of 5 | * JSONObject.toString(), JSONArray.toString(), 6 | * and JSONWriter.value(Object). The 7 | * toJSONString method will be used instead of the default behavior 8 | * of using the Object's toString() method and quoting the result. 9 | */ 10 | public interface JSONString { 11 | /** 12 | * The toJSONString method allows a class to produce its own JSON 13 | * serialization. 14 | * 15 | * @return A strictly syntactically correct JSON text. 16 | */ 17 | public String toJSONString(); 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/main/java/org/json/JSONTokener.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.io.Reader; 8 | import java.io.StringReader; 9 | 10 | /* 11 | Copyright (c) 2002 JSON.org 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | The Software shall be used for Good, not Evil. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | */ 33 | 34 | /** 35 | * A JSONTokener takes a source string and extracts characters and tokens from 36 | * it. It is used by the JSONObject and JSONArray constructors to parse 37 | * JSON source strings. 38 | * @author JSON.org 39 | * @version 2014-05-03 40 | */ 41 | public class JSONTokener { 42 | 43 | private long character; 44 | private boolean eof; 45 | private long index; 46 | private long line; 47 | private char previous; 48 | private Reader reader; 49 | private boolean usePrevious; 50 | 51 | 52 | /** 53 | * Construct a JSONTokener from a Reader. 54 | * 55 | * @param reader A reader. 56 | */ 57 | public JSONTokener(Reader reader) { 58 | this.reader = reader.markSupported() 59 | ? reader 60 | : new BufferedReader(reader); 61 | this.eof = false; 62 | this.usePrevious = false; 63 | this.previous = 0; 64 | this.index = 0; 65 | this.character = 1; 66 | this.line = 1; 67 | } 68 | 69 | 70 | /** 71 | * Construct a JSONTokener from an InputStream. 72 | * @param inputStream The source. 73 | */ 74 | public JSONTokener(InputStream inputStream) throws JSONException { 75 | this(new InputStreamReader(inputStream)); 76 | } 77 | 78 | 79 | /** 80 | * Construct a JSONTokener from a string. 81 | * 82 | * @param s A source string. 83 | */ 84 | public JSONTokener(String s) { 85 | this(new StringReader(s)); 86 | } 87 | 88 | 89 | /** 90 | * Back up one character. This provides a sort of lookahead capability, 91 | * so that you can test for a digit or letter before attempting to parse 92 | * the next number or identifier. 93 | */ 94 | public void back() throws JSONException { 95 | if (this.usePrevious || this.index <= 0) { 96 | throw new JSONException("Stepping back two steps is not supported"); 97 | } 98 | this.index -= 1; 99 | this.character -= 1; 100 | this.usePrevious = true; 101 | this.eof = false; 102 | } 103 | 104 | 105 | /** 106 | * Get the hex value of a character (base16). 107 | * @param c A character between '0' and '9' or between 'A' and 'F' or 108 | * between 'a' and 'f'. 109 | * @return An int between 0 and 15, or -1 if c was not a hex digit. 110 | */ 111 | public static int dehexchar(char c) { 112 | if (c >= '0' && c <= '9') { 113 | return c - '0'; 114 | } 115 | if (c >= 'A' && c <= 'F') { 116 | return c - ('A' - 10); 117 | } 118 | if (c >= 'a' && c <= 'f') { 119 | return c - ('a' - 10); 120 | } 121 | return -1; 122 | } 123 | 124 | public boolean end() { 125 | return this.eof && !this.usePrevious; 126 | } 127 | 128 | 129 | /** 130 | * Determine if the source string still contains characters that next() 131 | * can consume. 132 | * @return true if not yet at the end of the source. 133 | */ 134 | public boolean more() throws JSONException { 135 | this.next(); 136 | if (this.end()) { 137 | return false; 138 | } 139 | this.back(); 140 | return true; 141 | } 142 | 143 | 144 | /** 145 | * Get the next character in the source string. 146 | * 147 | * @return The next character, or 0 if past the end of the source string. 148 | */ 149 | public char next() throws JSONException { 150 | int c; 151 | if (this.usePrevious) { 152 | this.usePrevious = false; 153 | c = this.previous; 154 | } else { 155 | try { 156 | c = this.reader.read(); 157 | } catch (IOException exception) { 158 | throw new JSONException(exception); 159 | } 160 | 161 | if (c <= 0) { // End of stream 162 | this.eof = true; 163 | c = 0; 164 | } 165 | } 166 | this.index += 1; 167 | if (this.previous == '\r') { 168 | this.line += 1; 169 | this.character = c == '\n' ? 0 : 1; 170 | } else if (c == '\n') { 171 | this.line += 1; 172 | this.character = 0; 173 | } else { 174 | this.character += 1; 175 | } 176 | this.previous = (char) c; 177 | return this.previous; 178 | } 179 | 180 | 181 | /** 182 | * Consume the next character, and check that it matches a specified 183 | * character. 184 | * @param c The character to match. 185 | * @return The character. 186 | * @throws JSONException if the character does not match. 187 | */ 188 | public char next(char c) throws JSONException { 189 | char n = this.next(); 190 | if (n != c) { 191 | throw this.syntaxError("Expected '" + c + "' and instead saw '" + 192 | n + "'"); 193 | } 194 | return n; 195 | } 196 | 197 | 198 | /** 199 | * Get the next n characters. 200 | * 201 | * @param n The number of characters to take. 202 | * @return A string of n characters. 203 | * @throws JSONException 204 | * Substring bounds error if there are not 205 | * n characters remaining in the source string. 206 | */ 207 | public String next(int n) throws JSONException { 208 | if (n == 0) { 209 | return ""; 210 | } 211 | 212 | char[] chars = new char[n]; 213 | int pos = 0; 214 | 215 | while (pos < n) { 216 | chars[pos] = this.next(); 217 | if (this.end()) { 218 | throw this.syntaxError("Substring bounds error"); 219 | } 220 | pos += 1; 221 | } 222 | return new String(chars); 223 | } 224 | 225 | 226 | /** 227 | * Get the next char in the string, skipping whitespace. 228 | * @throws JSONException 229 | * @return A character, or 0 if there are no more characters. 230 | */ 231 | public char nextClean() throws JSONException { 232 | for (;;) { 233 | char c = this.next(); 234 | if (c == 0 || c > ' ') { 235 | return c; 236 | } 237 | } 238 | } 239 | 240 | 241 | /** 242 | * Return the characters up to the next close quote character. 243 | * Backslash processing is done. The formal JSON format does not 244 | * allow strings in single quotes, but an implementation is allowed to 245 | * accept them. 246 | * @param quote The quoting character, either 247 | * " (double quote) or 248 | * ' (single quote). 249 | * @return A String. 250 | * @throws JSONException Unterminated string. 251 | */ 252 | public String nextString(char quote) throws JSONException { 253 | char c; 254 | StringBuilder sb = new StringBuilder(); 255 | for (;;) { 256 | c = this.next(); 257 | switch (c) { 258 | case 0: 259 | case '\n': 260 | case '\r': 261 | throw this.syntaxError("Unterminated string"); 262 | case '\\': 263 | c = this.next(); 264 | switch (c) { 265 | case 'b': 266 | sb.append('\b'); 267 | break; 268 | case 't': 269 | sb.append('\t'); 270 | break; 271 | case 'n': 272 | sb.append('\n'); 273 | break; 274 | case 'f': 275 | sb.append('\f'); 276 | break; 277 | case 'r': 278 | sb.append('\r'); 279 | break; 280 | case 'u': 281 | sb.append((char)Integer.parseInt(this.next(4), 16)); 282 | break; 283 | case '"': 284 | case '\'': 285 | case '\\': 286 | case '/': 287 | sb.append(c); 288 | break; 289 | default: 290 | throw this.syntaxError("Illegal escape."); 291 | } 292 | break; 293 | default: 294 | if (c == quote) { 295 | return sb.toString(); 296 | } 297 | sb.append(c); 298 | } 299 | } 300 | } 301 | 302 | 303 | /** 304 | * Get the text up but not including the specified character or the 305 | * end of line, whichever comes first. 306 | * @param delimiter A delimiter character. 307 | * @return A string. 308 | */ 309 | public String nextTo(char delimiter) throws JSONException { 310 | StringBuilder sb = new StringBuilder(); 311 | for (;;) { 312 | char c = this.next(); 313 | if (c == delimiter || c == 0 || c == '\n' || c == '\r') { 314 | if (c != 0) { 315 | this.back(); 316 | } 317 | return sb.toString().trim(); 318 | } 319 | sb.append(c); 320 | } 321 | } 322 | 323 | 324 | /** 325 | * Get the text up but not including one of the specified delimiter 326 | * characters or the end of line, whichever comes first. 327 | * @param delimiters A set of delimiter characters. 328 | * @return A string, trimmed. 329 | */ 330 | public String nextTo(String delimiters) throws JSONException { 331 | char c; 332 | StringBuilder sb = new StringBuilder(); 333 | for (;;) { 334 | c = this.next(); 335 | if (delimiters.indexOf(c) >= 0 || c == 0 || 336 | c == '\n' || c == '\r') { 337 | if (c != 0) { 338 | this.back(); 339 | } 340 | return sb.toString().trim(); 341 | } 342 | sb.append(c); 343 | } 344 | } 345 | 346 | 347 | /** 348 | * Get the next value. The value can be a Boolean, Double, Integer, 349 | * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. 350 | * @throws JSONException If syntax error. 351 | * 352 | * @return An object. 353 | */ 354 | public Object nextValue() throws JSONException { 355 | char c = this.nextClean(); 356 | String string; 357 | 358 | switch (c) { 359 | case '"': 360 | case '\'': 361 | return this.nextString(c); 362 | case '{': 363 | this.back(); 364 | return new org.json.JSONObject(this); 365 | case '[': 366 | this.back(); 367 | return new org.json.JSONArray(this); 368 | } 369 | 370 | /* 371 | * Handle unquoted text. This could be the values true, false, or 372 | * null, or it can be a number. An implementation (such as this one) 373 | * is allowed to also accept non-standard forms. 374 | * 375 | * Accumulate characters until we reach the end of the text or a 376 | * formatting character. 377 | */ 378 | 379 | StringBuilder sb = new StringBuilder(); 380 | while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { 381 | sb.append(c); 382 | c = this.next(); 383 | } 384 | this.back(); 385 | 386 | string = sb.toString().trim(); 387 | if ("".equals(string)) { 388 | throw this.syntaxError("Missing value"); 389 | } 390 | return JSONObject.stringToValue(string); 391 | } 392 | 393 | 394 | /** 395 | * Skip characters until the next character is the requested character. 396 | * If the requested character is not found, no characters are skipped. 397 | * @param to A character to skip to. 398 | * @return The requested character, or zero if the requested character 399 | * is not found. 400 | */ 401 | public char skipTo(char to) throws JSONException { 402 | char c; 403 | try { 404 | long startIndex = this.index; 405 | long startCharacter = this.character; 406 | long startLine = this.line; 407 | this.reader.mark(1000000); 408 | do { 409 | c = this.next(); 410 | if (c == 0) { 411 | this.reader.reset(); 412 | this.index = startIndex; 413 | this.character = startCharacter; 414 | this.line = startLine; 415 | return c; 416 | } 417 | } while (c != to); 418 | } catch (IOException exception) { 419 | throw new JSONException(exception); 420 | } 421 | this.back(); 422 | return c; 423 | } 424 | 425 | 426 | /** 427 | * Make a JSONException to signal a syntax error. 428 | * 429 | * @param message The error message. 430 | * @return A JSONException object, suitable for throwing 431 | */ 432 | public JSONException syntaxError(String message) { 433 | return new JSONException(message + this.toString()); 434 | } 435 | 436 | 437 | /** 438 | * Make a printable string of this JSONTokener. 439 | * 440 | * @return " at {index} [character {character} line {line}]" 441 | */ 442 | public String toString() { 443 | return " at " + this.index + " [character " + this.character + " line " + 444 | this.line + "]"; 445 | } 446 | } 447 | -------------------------------------------------------------------------------- /lib/src/main/resources/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: com.jsonformat.Main 3 | 4 | -------------------------------------------------------------------------------- /lib/src/main/resources/META-INF/services/javax.annotation.processing.Processor: -------------------------------------------------------------------------------- 1 | kale.net.json.processor.Json2ModelProcessor -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':lib' 2 | --------------------------------------------------------------------------------