Closed westito closed 8 years ago
I don't really understand the issue. Can you show a chunk of code to make it clearer ?
inline fun <reified T: Any> DataSnapshot.toObject(): T? = try { Dep.gson.fromJson<T>(JsonHelpers.getMapper().writeValueAsString(this.value)) } catch (e: Exception) { e.printStackTrace() Crashlytics.logException(e) null }
it.toObject<Map<String, Competition2>>()?.let {...
I used this code and worked perfectly until the last version. I found a solution. Wrapped in a class and now it's working class CompetitionPair : Map<String, Competition2>()
I have a related issue:
I try to map a JSON list to my custom Object list with Kotson's extensions:
Gson().fromJson<List<MyCustomObj>>(json)
Instead of my List<MyCustomObj>
, I get a List<LinkedTreeMap>
(which is Gsons default).
This has been working in 1.7 version, and to me it seems that there may be an issue in GsonBuilder.kt in the typeToken
function:
inline fun <reified T: Any> typeToken(): Type {
val type = object : TypeToken<T>() {} .type
if (type is ParameterizedType) {
if (type.actualTypeArguments.any { it is WildcardType }) {
if (!type.actualTypeArguments.all { it is WildcardType })
throw IllegalArgumentException("Either none or all type parameters can be wildcard in $type")
return type.rawType
}
}
return type
}
In particular, I think the return type.rawType
does not make sense, since it now returns the rawtype (List) as soon as at least one single argument is a WildcardType. I think this may be a typo?
If it's not a typo and wanted behaviour, could you shed some light on why you introduced that check, and how one could work around it? I think part of my problem is, that Kotlin's list classes always resolve to bounded parameterized Lists List<? extends MyType>
...
Yes, this is an unwanted behaviour, for which I apologize.
I think that it is indeed because Kotlin's List
interface has declaration site variance.
This will be corrected first thing in the morning (Paris time).
Thanks, no need to apologize, bugs happen :-) I appreciate your efforts, great library.
OK, I've just pushed 2.0.1 in Maven Central that corrects this bug.
Now for the _why_:
Let's say I have a class Command<T>
. Using Kotson, I want to be able to register a type adapter on Command<*>
. Meaning that I want to be able to register a serializer / deserializer on any Command
. That was not really possible in v1.7 because the typeToken
function would return the ParameterizedType Command<?>
, and not class Command
. So later when Gson would saw that it has to deserialize, say, a Command<Person>
, it would not match. The only way was to use registerTypeHierarchyAdapter
instead of registerTypeAdapter
because it uses a Class
and not a Type
, which was not really semantic.
So the idea was to detect in the typeToken
function if a generic Command<*>
was used, in which case register the Class
so that any Command
would be deserialized accordingly. If a specialized Command<Whatever>
was used, then it would return the classic ParameterizedType
.
That's the reason of the "Either none or all type parameters can be wildcard". Really, Gson can't handle a semi-generalized type adapter such as Map<String, *>
.
Now, of course, I forgot to take into account that, in java, List<?>
is really List<? extends Object>
. Meaning that both List<?>
and List<? extends Person>
are both ParameterizedType
with a WildCardType
argument. You know the rest.
Now, I've corrected my mistake by having typeToken
revert to it's old behaviour, and having registerTypeAdapter
use a registrationTypeToken
function. This new registrationTypeToken
function acts as explained, returning the Class
and not ParameterizedType
when a wildcard is used, only now it also checks that the wildcard has Object
in it's upper bound, in order to differentiate List<*>
and List<out Whatever>
.
I'm not an expert in Java reflexivity so please do let me know if you think this is not the best course of action ;)
TLDR; Koston 2.0.1
is in Maven Central. It should correct the issue. Please let me know if it doesn't.
Thanks for the report, and sorry for the inconvenience ;)
Thank you, I don't know if I get to test it today or tomorrow, but definitely in the next days. Thank you for the quick fix!
Ok, I can confirm the bug is fixed :) Thanks for your efforts!
I get "Either none or all type parameters can be wildcard in Map<String, Competition2>" when pass this Map class as parameter. This worked in the previous version. Without kotson gson can handle it well.