json-iterator / java

jsoniter (json-iterator) is fast and flexible JSON parser available in Java and Go
http://jsoniter.com/
MIT License
1.5k stars 517 forks source link

Android projects codegeneration support #128

Open ancientloregames opened 6 years ago

ancientloregames commented 6 years ago

My team was impressed by the performance of your API in various benchmarks so we tried to replace Gson in our project with it, however we've faced some issues integrating it. At first, I tried to use Dynamic Codegen on a simple text project. The model is plain as desk:

public class Model
{
    public int int1;
    public int int2;
}

But I get exception:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bitrix.a01_test_jsoniter/com.bitrix.a01_test_jsoniter.MainActivity}: com.jsoniter.spi.JsonException: failed to generate decoder for: com.jsoniter.spi.ClassInfo@c4e768c with [], exception: javassist.NotFoundException: com.jsoniter.spi.Decoder
public static java.lang.Object decode_(com.jsoniter.JsonIterator iter) throws java.io.IOException { java.lang.Object existingObj = com.jsoniter.CodegenAccess.resetExistingObject(iter);
..........
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
    at android.app.ActivityThread.-wrap11(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5417)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
 Caused by: com.jsoniter.spi.JsonException: failed to generate decoder for: com.jsoniter.spi.ClassInfo@c4e768c with [], exception: javassist.NotFoundException: com.jsoniter.spi.Decoder
public static java.lang.Object decode_(com.jsoniter.JsonIterator iter) throws java.io.IOException { java.lang.Object existingObj = com.jsoniter.CodegenAccess.resetExistingObject(iter);
..........

I take it, the reason is some compatibility issue with Javassist. So I tried to implement Static Codegen Wrapper.

public class ModelCodegenConfig implements StaticCodegenConfig
{
    @Override
    public void setup()
    {
        JsoniterSpi.registerPropertyDecoder(Model.class, "int1", new Decoder.IntDecoder()
        {
            @Override
            public int decodeInt(JsonIterator iter) throws IOException
            {
                return Integer.valueOf(iter.readString());
            }
        });
        JsoniterSpi.registerPropertyDecoder(Model.class, "int2", new Decoder.IntDecoder()
        {
            @Override
            public int decodeInt(JsonIterator iter) throws IOException
            {
                return Integer.valueOf(iter.readString());
            }
        });
    }
    @Override
    public TypeLiteral[] whatToCodegen()
    {
        return new TypeLiteral[] {
                TypeLiteral.create(int.class)
        };
    }
    public static void main(String[] args) throws Exception
    {
        StaticCodegen.main(new String[] { ModelCodegenConfig.class.getCanonicalName() });
    }
}

But I continue facing crashes with the following log:

 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bitrix.a01_test_jsoniter/com.bitrix.a01_test_jsoniter.MainActivity}: com.jsoniter.spi.JsonException: static gen should provide the decoder we need, but failed to create the decoder
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
  at android.app.ActivityThread.-wrap11(ActivityThread.java)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
  at android.os.Handler.dispatchMessage(Handler.java:102)
  at android.os.Looper.loop(Looper.java:148)
  at android.app.ActivityThread.main(ActivityThread.java:5417)
  at java.lang.reflect.Method.invoke(Native Method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: com.jsoniter.spi.JsonException: static gen should provide the decoder we need, but failed to create the decoder
  at com.jsoniter.Codegen.gen(Codegen.java:64)
  at com.jsoniter.Codegen.getDecoder(Codegen.java:25)
  at com.jsoniter.JsonIterator.read(JsonIterator.java:369)
  at com.jsoniter.JsonIterator.read(JsonIterator.java:359)
  at com.jsoniter.JsonIterator.deserialize(JsonIterator.java:425)
  at com.jsoniter.JsonIterator.deserialize(JsonIterator.java:395)
  at com.bitrix.a01_test_jsoniter.MainActivity.onCreate(MainActivity.java:29)
  at android.app.Activity.performCreate(Activity.java:6251)
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
  at android.app.ActivityThread.-wrap11(ActivityThread.java) 
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
  at android.os.Handler.dispatchMessage(Handler.java:102) 
  at android.os.Looper.loop(Looper.java:148) 
  at android.app.ActivityThread.main(ActivityThread.java:5417) 
  at java.lang.reflect.Method.invoke(Native Method) 
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Caused by: java.lang.ClassNotFoundException: jsoniter_codegen.cfg4.decoder.com.bitrix.a01_test_jsoniter.Model
  at java.lang.Class.classForName(Native Method)
  at java.lang.Class.forName(Class.java:324)
  at java.lang.Class.forName(Class.java:285)
  at com.jsoniter.Codegen.gen(Codegen.java:60)
  at com.jsoniter.Codegen.getDecoder(Codegen.java:25) 
  at com.jsoniter.JsonIterator.read(JsonIterator.java:369) 
  at com.jsoniter.JsonIterator.read(JsonIterator.java:359) 
  at com.jsoniter.JsonIterator.deserialize(JsonIterator.java:425) 
  at com.jsoniter.JsonIterator.deserialize(JsonIterator.java:395) 
  at com.bitrix.a01_test_jsoniter.MainActivity.onCreate(MainActivity.java:29) 
  at android.app.Activity.performCreate(Activity.java:6251) 
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
  at android.app.ActivityThread.-wrap11(ActivityThread.java) 
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
  at android.os.Handler.dispatchMessage(Handler.java:102) 
  at android.os.Looper.loop(Looper.java:148) 
  at android.app.ActivityThread.main(ActivityThread.java:5417) 
  at java.lang.reflect.Method.invoke(Native Method) 
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Caused by: java.lang.ClassNotFoundException: Didn't find class "jsoniter_codegen.cfg4.decoder.com.bitrix.a01_test_jsoniter.Model" on path: DexPathList[[zip file "/data/app/com.bitrix.a01_test_jsoniter-1/base.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_dependencies_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_0_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_1_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_2_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_3_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_4_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_5_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_6_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_7_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_8_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/com.bitrix.a01_test_jsoniter-1/lib/arm, /vendor/lib, /system/lib]]
  at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
  at java.lang.Class.classForName(Native Method) 
  at java.lang.Class.forName(Class.java:324) 
  at java.lang.Class.forName(Class.java:285) 
  at com.jsoniter.Codegen.gen(Codegen.java:60) 
  at com.jsoniter.Codegen.getDecoder(Codegen.java:25) 
  at com.jsoniter.JsonIterator.read(JsonIterator.java:369) 
  at com.jsoniter.JsonIterator.read(JsonIterator.java:359) 
  at com.jsoniter.JsonIterator.deserialize(JsonIterator.java:425) 
  at com.jsoniter.JsonIterator.deserialize(JsonIterator.java:395) 
  at com.bitrix.a01_test_jsoniter.MainActivity.onCreate(MainActivity.java:29) 
  at android.app.Activity.performCreate(Activity.java:6251) 
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
  at android.app.ActivityThread.-wrap11(ActivityThread.java) 
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
  at android.os.Handler.dispatchMessage(Handler.java:102) 
  at android.os.Looper.loop(Looper.java:148) 
  at android.app.ActivityThread.main(ActivityThread.java:5417) 
  at java.lang.reflect.Method.invoke(Native Method) 
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Suppressed: java.lang.ClassNotFoundException: jsoniter_codegen.cfg4.decoder.com.bitrix.a01_test_jsoniter.Model
  at java.lang.Class.classForName(Native Method)
  at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
  at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
        ... 23 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available

Am I doing something wrong, or your project is simply not compatible with Android? Will it be in near future?

taowen commented 6 years ago

it is compatible with android. which mode are you trying to use, reflection or static codegen?

On Thursday, December 7, 2017, Nickolas M. notifications@github.com wrote:

My team was impressed by the performance of your API in various benchmarks so we tried to replace Gson in our project with it, however we've faced some issues integrating it. At first, I tried to use Dynamic Codegen on a simple text project. The model is plain as desk:

public class Model { public int int1; public int int2; }

But I get exception:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bitrix.a01_test_jsoniter/com.bitrix.a01_testjsoniter.MainActivity}: com.jsoniter.spi.JsonException: failed to generate decoder for: com.jsoniter.spi.ClassInfo@c4e768c with [], exception: javassist.NotFoundException: com.jsoniter.spi.Decoder public static java.lang.Object decode(com.jsoniter.JsonIterator iter) throws java.io.IOException { java.lang.Object existingObj = com.jsoniter.CodegenAccess.resetExistingObject(iter); .......... at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) at android.app.ActivityThread.-wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: com.jsoniter.spi.JsonException: failed to generate decoder for: com.jsoniter.spi.ClassInfo@c4e768c with [], exception: javassist.NotFoundException: com.jsoniter.spi.Decoder public static java.lang.Object decode_(com.jsoniter.JsonIterator iter) throws java.io.IOException { java.lang.Object existingObj = com.jsoniter.CodegenAccess.resetExistingObject(iter); ..........

I take it, the reason is some compatibility issue with Javassist. So I tried to implement Static Codegen Wrapper.

public class ModelCodegenConfig implements StaticCodegenConfig { @Override public void setup() { JsoniterSpi.registerPropertyDecoder(Model.class, "int1", new Decoder.IntDecoder() { @Override public int decodeInt(JsonIterator iter) throws IOException { return Integer.valueOf(iter.readString()); } }); JsoniterSpi.registerPropertyDecoder(Model.class, "int2", new Decoder.IntDecoder() { @Override public int decodeInt(JsonIterator iter) throws IOException { return Integer.valueOf(iter.readString()); } }); } @Override public TypeLiteral[] whatToCodegen() { return new TypeLiteral[] { TypeLiteral.create(int.class) }; } public static void main(String[] args) throws Exception { StaticCodegen.main(new String[] { ModelCodegenConfig.class.getCanonicalName() }); } }

But I continue facing crashes with the following log:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bitrix.a01_test_jsoniter/com.bitrix.a01_test_jsoniter.MainActivity}: com.jsoniter.spi.JsonException: static gen should provide the decoder we need, but failed to create the decoder at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) at android.app.ActivityThread.-wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: com.jsoniter.spi.JsonException: static gen should provide the decoder we need, but failed to create the decoder at com.jsoniter.Codegen.gen(Codegen.java:64) at com.jsoniter.Codegen.getDecoder(Codegen.java:25) at com.jsoniter.JsonIterator.read(JsonIterator.java:369) at com.jsoniter.JsonIterator.read(JsonIterator.java:359) at com.jsoniter.JsonIterator.deserialize(JsonIterator.java:425) at com.jsoniter.JsonIterator.deserialize(JsonIterator.java:395) at com.bitrix.a01_test_jsoniter.MainActivity.onCreate(MainActivity.java:29) at android.app.Activity.performCreate(Activity.java:6251) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) at android.app.ActivityThread.-wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: java.lang.ClassNotFoundException: jsoniter_codegen.cfg4.decoder.com.bitrix.a01_test_jsoniter.Model at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:324) at java.lang.Class.forName(Class.java:285) at com.jsoniter.Codegen.gen(Codegen.java:60) at com.jsoniter.Codegen.getDecoder(Codegen.java:25) at com.jsoniter.JsonIterator.read(JsonIterator.java:369) at com.jsoniter.JsonIterator.read(JsonIterator.java:359) at com.jsoniter.JsonIterator.deserialize(JsonIterator.java:425) at com.jsoniter.JsonIterator.deserialize(JsonIterator.java:395) at com.bitrix.a01_test_jsoniter.MainActivity.onCreate(MainActivity.java:29) at android.app.Activity.performCreate(Activity.java:6251) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) at android.app.ActivityThread.-wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: java.lang.ClassNotFoundException: Didn't find class "jsoniter_codegen.cfg4.decoder.com.bitrix.a01_test_jsoniter.Model" on path: DexPathList[[zip file "/data/app/com.bitrix.a01_test_jsoniter-1/base.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_dependencies_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_0_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_1_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_2_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_3_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_4_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_5_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_6_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_7_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_8_apk.apk", zip file "/data/app/com.bitrix.a01_test_jsoniter-1/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/com.bitrix.a01_test_jsoniter-1/lib/arm, /vendor/lib, /system/lib]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at java.lang.ClassLoader.loadClass(ClassLoader.java:511) at java.lang.ClassLoader.loadClass(ClassLoader.java:469) at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:324) at java.lang.Class.forName(Class.java:285) at com.jsoniter.Codegen.gen(Codegen.java:60) at com.jsoniter.Codegen.getDecoder(Codegen.java:25) at com.jsoniter.JsonIterator.read(JsonIterator.java:369) at com.jsoniter.JsonIterator.read(JsonIterator.java:359) at com.jsoniter.JsonIterator.deserialize(JsonIterator.java:425) at com.jsoniter.JsonIterator.deserialize(JsonIterator.java:395) at com.bitrix.a01_test_jsoniter.MainActivity.onCreate(MainActivity.java:29) at android.app.Activity.performCreate(Activity.java:6251) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) at android.app.ActivityThread.-wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Suppressed: java.lang.ClassNotFoundException: jsoniter_codegen.cfg4.decoder.com.bitrix.a01_test_jsoniter.Model at java.lang.Class.classForName(Native Method) at java.lang.BootClassLoader.findClass(ClassLoader.java:781) at java.lang.BootClassLoader.loadClass(ClassLoader.java:841) at java.lang.ClassLoader.loadClass(ClassLoader.java:504) ... 23 more Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available

Am I doing something wrong, or your project is simply not compatible with Android? Will it be in near future?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/json-iterator/java/issues/128, or mute the thread https://github.com/notifications/unsubscribe-auth/AACeXUsR35rdHBOF-pGASBeVUgGGZmNtks5s9_lHgaJpZM4Q5ptw .

taowen commented 6 years ago

http://jsoniter.com/java-features.html#reflection mode is still faster than gson, you can start from there. I will provide a full example on Android + static code generation once I am back home. Currently on the road, do not have time to work on this.

ancientloregames commented 6 years ago

Thanks for your response! I've tried both codegen methods, and haven't tried reflection. So, is dynamic codegen confirmed not to be an option for Android?

taowen commented 6 years ago

dynamic codegen is not compatible with android

On Monday, December 11, 2017, Nickolas M. notifications@github.com wrote:

Thanks for your response! I've tried both codegen methods, and haven't tried reflection. So, is dynamic codegen confirmed not to be an option for Android?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/json-iterator/java/issues/128#issuecomment-350735994, or mute the thread https://github.com/notifications/unsubscribe-auth/AACeXZBHSsPF6Td8JbO7_DT9kOaj1yBkks5s_TkggaJpZM4Q5ptw .

ancientloregames commented 6 years ago

I've managed to replace Gson with your library (Reflective mode). It does work faster (up to three times)! Nicely done! Can't wait for you explanation of how to work with the static codegen properly.

taowen commented 6 years ago

please refer to https://github.com/json-iterator/java/blob/master/android-demo/build.gradle

this is the generated code: https://github.com/json-iterator/java/tree/master/android-demo/src/main/java/jsoniter_codegen/cfg1173796797

ancientloregames commented 6 years ago

Hi. I've tried to build your sample project for android, but keep getting following exception in the Gradle Console during the assemly:

Exception in thread "main" java.lang.ClassNotFoundException: com.example.myapplication.DemoCodegenConfig
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at com.jsoniter.static_codegen.StaticCodegen.main(StaticCodegen.java:31)

 FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':generateSources'.
> Process 'command '/home/colfair/android-studio/jre/bin/java'' finished with non-zero exit value 1
taowen commented 6 years ago

try comment out

afterEvaluate {
    android.applicationVariants.all { variant ->
        variant.javaCompiler.dependsOn(generateSources)
    }
}

and build, then build again. It referenced the classes output, which is a circular dependency.

taowen commented 6 years ago

see the latest https://github.com/json-iterator/java/blob/master/android-demo/build.gradle

it should be fixed now

ancientloregames commented 6 years ago

Thanks for your fast replies! Your fix works fine in the sample project. However, I have some complications in implementing it into my team's project. The dependency on your library itself must be in our library module, witch is, in its turn, to be included to the application module, so I tried to put the task execution into the application module, but an exception, similar to the previous one, occurs: Execution failed for task ':jsoniterStaticCodgen'. > Process 'command '/home/colfair/android-studio/jre/bin/java'' finished with non-zero exit value 1 Without any further explanation. Tried to move task to the library module and change the collection of build variants to the libraryVariants. Same exception.

nedtwigg commented 6 years ago

If you'd like another approach, you could put these files into your buildSrc, and then this into your build.gradle.

taowen commented 6 years ago

@nedtwigg thanks! if want to merge your plugin into jsoniter, just give me a pull request.

nedtwigg commented 6 years ago

I'd love to donate the plugin! The hard part is integrating it into your build / release process, and putting it on the Gradle Plugin Portal, which is hard as third party. The plugin itself is just a few lines, feel free to just nab it if you're up for taking over deployment. I'd be happy to help answer questions & maintain it.

taowen commented 6 years ago

I am unfamiliar with gradle build system. Would like to keep this for community support :)

nedtwigg commented 6 years ago

Ha, and I know nothing about maven ;-) Looks like there's a gradle-maven-plugin for calling gradle from maven. If you make a folder with that plugin inside that supports publish, test, I'd be happy to stick the appropriate gradle build into it :)

taowen commented 6 years ago

what is the process to put things into Gradle Plugin Portal?

nedtwigg commented 6 years ago

You create an account here: https://login.gradle.org/user/register

If you publish interactively (at the console), you login via the console each time you publish. Or you can get an API key and do headless publish in CI. You shouldn't have to make changes to the plugin very often (it doesn't care what version of json-iterator the user is using), so manual publish would be fine.

Then you will be in these search results: https://plugins.gradle.org/search?term=json

ancientloregames commented 6 years ago

Hi! Sorry for no participating in resolving the issue for so long time. Was busy with some other stuff, so I sticked with reflective approach for a while. Finally, I've got some time. I figured out that the reason your build task not working in my project is the gradle version I use (4+). It uses api and implementation instead of compile for dependencies, so Compile Configuration will not provide the local JVM with the needed classpath. Unfortunately api and implementation Configurations are unresolvable. I've found another approach, which involves setting the classpath on afterEvaluate as followed:

afterEvaluate {
    android.libraryVariants.each {
        Task task = jsoniterCodegen
        task.classpath += it.compileConfiguration
        it.javaCompiler.dependsOn task
    }
}

All looked fine on the simple test project, but on the actual one, I've faced new problem. This approach leads to an exception, if the project depends on another local project:

Error:Could not determine the dependencies of task ':jsoniter_lib:jsoniterCodegen'.
> Could not resolve all task dependencies for configuration ':jsoniter_lib:releaseCompileClasspath'.
   > More than one variant of project :sublib matches the consumer attributes:
       - Configuration ':sublib:releaseApiElements' variant android-aidl:
           - Found artifactType 'android-aidl' but wasn't required.
           - Required com.android.build.api.attributes.BuildTypeAttr 'release' and found compatible value 'release'.
           - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
           - Found com.android.build.gradle.internal.dependency.VariantAttr 'release' but wasn't required.
           - Required org.gradle.api.attributes.Usage 'java-api' and found compatible value 'java-api'.

As the last resort, I managed to create custom Configuration and provide it with the required dependencies.

afterEvaluate {
    Configuration jsonConf = configurations.create("jsonConf")
    jsonConf.defaultDependencies {
        it.add(owner.project.dependencies.create("com.jsoniter:jsoniter:0.9.21"))
    }
    android.libraryVariants.each {
        Task task = jsoniterCodgen
        task.classpath += jsonConf
        it.javaCompiler.dependsOn task
    }
}

But this code looks really nasty to my taste. Any thoughts on how to improve it?