-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handling Nulls Inside Lists where List Element Type is @NotNull #2500
Comments
This is probably more related Kotlin (although certainly would need help from databind), since core Jackson has absolutely no idea of But one big challenge is that although databind does have many mechanisms for skipping or ignoring Having said that, Jackson 2.9 did add significantly to configurability of null handling, with annotations like:
(see https://medium.com/@cowtowncoder/jackson-2-9-features-b2a19029e9ff under "Null replacement/error/skipping (on deserialization)") which would seem promising, but. This annotation allows specifying handling for both values of properties ("main" So: I think this might work for you. I think Kotlin module does not change Collection handling a lot, so it might "just work". Unit tests for pure Java can be found from:
|
Hey @cowtowncoder thank you for the response! I don't expect It's for that reason that I'm writing you here to understand what we can do in Kotlin using just the I know there are a lot of bindings available in Jackson for modifying functionality; are there any you see that would work somewhat similarly (via annotation, ideally, but open to other solutions) to what you described that Kotlin might support? It's these kinds of sharp edges I kept stumbling on while I was looking for a solution and I hoped that you or someone else here who knows Jackson deeply could help me find a good compromise. |
@mikeholler I don't think #250 is quite related here: TBH I am not sure I understand what user is trying to do there (and whether it should work or not), but it is not about But aside the question of making Now, back to
So I think we are on same page regarding finding mechanisms that can be used to support more natural handling from Kotlin POV. |
@cowtowncoder I have to pause on this for a bit today, but I want to partially reply to your comment so I can address the question about #250, which I think does apply:
The above test fails. Also, the following different annotation sites fail as well:
Note that |
This may be my biggest shot in the dark ever
I think this may be a/the solution? As a processor is better than runtime execution but you can simply include it as well... Everyones post is long so -
If you're in jdk 12 or up remember to provide your annotation to the annotation processor to your module-info.java
The exception you should be catching is ValidationException as well, all of these will throw it
Quick read up : https://www.baeldung.com/javax-validation |
@GedMarc you're absolutely right, and I applaud your creativity; javax validation is exactly where I reached after having so many issues with Jackson. But sadly, we meet another impasse: meet KT-13228. Kotlin does not yet support type annotations (which always surprises the heck out of me when I wait just long enough between uses to forget that that's the case). Looks like it's being added in 1.4, but it's not out yet 😢 |
@mikeholler not sure if that is sarcastic or not xD either way... Are you including the validation api?, or like hibernate or just referencing the java.activation library? You could possibly get around this by creating a reader that simply throws out the validation? This is a copy paste from my stuff, you can just throw it out in a reader.
|
wrong brain mode |
@GedMarc it's not sarcastic, it's a great idea but unfortunately not one I can use. We're using javax validation through Dropwizard's built-in model validation. I'd like it to work with that, but the lack of Kotlin type annotations got in the way. |
You don't need annotations this way :)
It works for me, hmmm.
|
@mikeholler Ok my bad on #250 then, I read it too quickly and somehow determined it was related to non-container properties of a data class. But as to Now, back to null-handling not working... I assume this class
essentially replaces what Another angle on null handling that might help is that instead of annotations, one can also use "config overrids" to specify defaults. Databind test
which should also achieve what you want for all properties with nominal (declared) type of Or, for even more global applicability:
where one caveat is that "content" refers to I guess I am mostly just interested in figuring out how to make Kotlin module not block use of this setting: I do not think there is anything fundamental preventing it but maybe some missing wiring. If Kotlin module had custom Collection deserializers, I would bet they were just missing handling of |
@cowtowncoder I can apply it to fields and constructors (that's what I did in my examples). They compile, Jackson just doesn't pick up how I'm trying to do it, even with the annotation site qualifiers like I really like the |
Ah. So I misunderstood that part wrt applicability. One other thing: it'd be good to debug as to whether problem comes down to annotation not being merge to appropriate property (and so not visible to deserializer factory etc), or just not being used. |
Thanks @cowtowncoder, give me until EOB tomorrow to get you a small example project with tests that verifies that. I'll make it nice and easy for you to get going. Just to be clear, you want an example of the |
For me test only needs to try to trigger expected behavior: it does not need to check bytecode or anything like that. I can observe (debugger or adding good old print statements :) ) what happens in places like creation and contextualization of Does this make more sense? The reason I want minimal case is just to reduce noise wrt resolution of things. |
Yeah for sure. I can absolutely put that together for you. |
@cowtowncoder in putting together what you asked, I ended up finding a solution to the problem. TL;DR, everything was fixed when I tried
I am really curious if you might know what change between |
That is an excellent outcome. I am not sure what might have fixed it... looking at release notes, I would guess that maybe #2280 did it? Or perhaps #2458. But difficult to know for sure. One follow-up question: is use of this feature that you could explain on, say, README? I know how it works in general but often am not the best person to explain it. And in case of Kotlin there's more context too. But having a brief usage sample for commonly expected usage seems useful. |
@cowtowncoder you're probably right that it was one of those two. Thanks for those links.
So, kinda? The tough part here is that I have this feeling that this should be the default behavior (failing fast and not allowing any nulls in a list by default, then overriding if nulls are needed is clearly the best outcome). It seems to me a large flaw in At its simplest, I could document the |
It could be a separate Wiki page for repo too -- Workarounds (or something) for Kotlin? |
Hey there! I'm using jackson-module-kotlin and I like my null safety, but Jackson doesn't appear to respect these desires. I've been fighting with this issue for nearly 4 hours, and the guidance I've found is very confusing. I'm creating the issue here because I believe the solution lies with
jackson-databind
and notjackson-module-kotlin
.ObjectWithStringList defines strings as List, which means that users should expect that the strings inside the list are never null (List<String?> would mean it could contain nulls). When I run this test, however, it fails (the exception is not thrown). What happens instead is result[1] evaluates to null, which should never happen according to Kotlin.
What do I want? Ideally I would want jackson-module-kotlin to respect collection element types' nullity, however I realize this is idealistic and may be difficult. Instead, I would like the default behavior of deserializing any list type with nulls (whether String or String?) to throw an exception. And then I would like some way to override this behavior if I really want to allow nulls in my list.
I've gone down the rabbit hole and tried a large number of things (which I can summarize upon request, but for brevity's sake, decided not to here), and have been unable to find anything acceptable. The best solution I've found so far is implementing my own collection type (see below) but the drawback to this solution is that I still want it to appear as List, not ArrayListOfNotNull.
Also note that this did not work (I was really hoping it would):
Even if it did work, however, it's not the default behavior (which was my original preference).
With the plethora of ways to integrate into Jackson Databind, what is the recommended approach here? Additionally, I have to believe this affects lots of Kotlin users, whether they realize it or not (and I think the latter is more likely). As a result, I'd like to see some documentation added for handling this type of situation, because I could not find much of substance.
The text was updated successfully, but these errors were encountered: