Dynamic types, groovy like json loading


#1

Hi,

one thing right now is preventing me from using kotlin at this time. I have some Android apps written mostly in Java with some parts in Groovy. The groovy part is som plain old groovy objects for communication with our REST-Service.
The JSON documents come in from our server and are being mapped to groovy objects via

MyGroovyType result = new JsonSlurper().parseText(json),

which calls the map constructor of the groovy class and maps the properties found in the json to the groovy properties. Is there any way I could do this in Kotlin?

Additionaly I let my groovy types implement the trait “DynamicProperties”

    trait DynamicProperties {
        def propertyMissing(String name) {
            //println "unknown property $name"
        }

        def propertyMissing(String name, value) {
    //        println "unknown property $name"
        }
    }

just in case some property is being added to the rest api, so the mapper doesn’t crash and older app versions can work with newer rest service versions.
What is the way you would do this in Kotlin?


#2

Anything that can be done in Java can be done in Kotlin. That line of Java in Kotlin is just the following and should work the same:

val result = JsonSlurper().parseText(json)

#3

i’m not sure about that supporting dynamic type at least on JVM 9 may result useful in some corner case like this, scripting or improve JVM/JS code compatibility.

Collect some opinions about this should be helpful.


#4

val result = JsonSlurper().parseText(json)

This line would create a map with the json properties, but groovy implicitly calls the constructor of MyGroovyType with that map, which results in a typed object. I prefer typed objects whenever possible and groovy does the trick to map the (untyped) json at the earliest possible time.


#5

Maybe one possibility would be to create an Annotation @MapConstructur on the class level to make the compiler generate a map constructur with named nullable arguments for this use case.


#6

I’m not addressing exactly this issue, my rationale is more general.

Supporting “dynamic” type on JVM backend may be helpful for developers?
Moreover Java 9 should be a special support for “dynamic” (“dyn:” prefix in invocation).

I recently wrote a piece of code with assumption that a library may be loaded or not using JVM reflection: this was really ugly compared to the Groovy way.


#7

I was assuming that line was in your Java code not in Groovy. The bottom line is that groovy should not be able to tell that it is called from Kotlin or Java. If somehow there is something that works in java but not Kotlin that is a serious bug and needs to be reported.

Have you tried adding Kotlin support to your project and then starting to convert Java files to Kotlin? The converter is not 100% reliable but once you work through any issues with the conversion there should be no difference in behavior.


#8

The thing is, it’s possible to compile java/kotlin or java/groovy together in one compile run and to mix those two languages together. If a add a third language to my project, that means I need to separate the source folders and I can only call one language from another, not the other direction. Thats why I’m not gonna add a third language before the second is gone. So I’m still with java/groovy. Groovy still has some cool features that kotline hasn’t, and the dynamic loading of json without explicit conversion is the one i’d miss most.
That said, I’d really like to see a groovy <-> java converter in intellij idea, that would help a lot with the migration.


#9

Just adding my voice here.

Please never implement “optional” typing!
The moment static typing becomes optional, that moment you can kiss goodbye on all benefits of static typing (reliable IDE refactorings, finding a lot of problems at compile time etc.).
Making dynamic typing an option will guarantee that people will use it, so in practice the static typing benefits will be gone.

I don’t know if Jackson runs on Android, but this is a classic case for it (or something similar). This should be solved through reflection, not through dynamic typing.


#10

I am not sure if it can be used on Android devices but did you already take a look at this project?


#11

That looks good, thanks for the hint. Will try it in the next days!


#12

Gosu has this capability via the Dynamic type:

var personUrl = new URL( "http://gosu-lang.github.io/data/person.json" )
var person: Dynamic = personUrl.JsonContent

Here person can be used to dynamically access Json feature e.g.,

print( person.Name )

But Gosu can also provide static typing for Json via structural types:

var person = Person.fromJsonUrl( personUrl )
print( person.Name )
print( person.Address.City )
print( person.Hobby[0].Name )

^^ all statically typed and IDE code-completed. Groovy can’t touch this.

Read more here:
https://gosu-lang.github.io/2016/03/01/new-json-support-in-gosu.html


#13

I disagree with some people here… if the JSON you work with changes often and you don’t control it, using Groovy and dynamic typing to handle seems perfectly reasonable.

If you try to use Jackson or Gson (which would work out-of-the-box if your type’s properties map correctly to the json) for that, any time your json changes, your code will crash.

That’s true for the Groovy implementation as well if any existing field changes type, but that should be very unlikely.