json-iterator / java

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

Dynamic code generation: support Kotlin data classes with non-nullable properties #170

Open elifarley opened 6 years ago

elifarley commented 6 years ago

It seems that Kotlin data classes with non-nullable properties or with immutable properties (val) don't get their values when deserialized.

Related: #55

taowen commented 6 years ago

I have no experience of kotlin. Any one can help on this?

Miha-x64 commented 6 years ago

Data classes themselves introduce nothing special — they implement hashCode, equals, toString and componentN functions automatically. Read-only proeprties (vals) are just private final fields with getters. So, Kotlin data class X(val a: String) if equivalent to

public final class X {
    private final String a;
    public X(String a) {
        this.a = a;
    }
    public String getA() { return a; }
    public String component1() { return a; }
    @Override public boolean equals(Object other) { ... }
    @Override public int hashCode() { ... }
    @Override public String toString() { ... }
}

componentN functions are for 'destructuring', for example

class FortyTwoTacos {
    operator fun component1() = 42
    operator fun component2() = "tacos"
}
val tacos = FortyTwoTacos()
val (count, what) = tacos // here count = component1(), what = component2()
println("$count $what") // 42 tacos

I've omitted types, but they are inferred. Kotlin is statically-typed and preserves them, and uses primitive Java types when possible, despite they are absent at language level.

So, class structure has no serious differences from Java's one.

elifarley commented 6 years ago

I think I'll get a list of all constructors, choose the one with the least amount of parameters, and provide non null values to them. If the parameters type is not a standard one like Long, String and such, then I don't know what the best approach would be...

Miha-x64 commented 6 years ago

Why non null? What if the value is nullable? With Gson, I just pass values 'as is' to constructor. If non-nullable value is null, let it be fail-fast. https://github.com/Miha-x64/gson-constructor-type-adapter-factory

elifarley commented 6 years ago

It already fails really fast ;)

The point of the current issue is to provide support for Kotlin classes with non-nullable properties.

Currently, null values are passed to the constructor, and the constructor throws an exception because the properties are non-nullable.

My idea is to change jsoniter library so that it chooses non-null values to pass to the constructor.

Miha-x64 commented 6 years ago

If there's no such value, what deserializer should do? Use defaults values? This will require kotlin-reflect then...

elifarley commented 6 years ago

Upon further reflection on this, I think the constructor should be called with the values read from the JSON being parsed. Otherwise, we'll have to pass it a default value and then call the Java reflection API to set any final fields to the desired values.

All of this should be doable without kotlin-reflect, I guess.